home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / ghostscript / 8.64 / Resource / Init / opdfread.ps < prev    next >
Encoding:
Text File  |  2009-04-17  |  137.7 KB  |  4,480 lines

  1. %!PS-Adobe-2.0
  2. %
  3. %        Copyright (C) 2002 Artifex Software, Inc.      All rights reserved.
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. % For more information about licensing, please refer to
  10. % http://www.ghostscript.com/licensing/. For information on
  11. % commercial licensing, go to http://www.artifex.com/licensing/ or
  12. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  13. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  14.  
  15. % $Id: opdfread.ps 9141 2008-10-10 08:51:42Z ken $
  16. % pdfread.ps - A procset for interpreting an ordered PDF 1.3 file.
  17.  
  18. % This module defines routines for interpreting a PDF file with
  19. % a Postscript interpreter. To convert a PDF file into Postscript 
  20. % just pre-contcatenate this file. The PDF file must satisfy 
  21. % few constraints :
  22. %
  23. % 1. It must contain only Postscript level 2 objects encoded with
  24. % the PDF 1.3 language. Higher PDF levels must be re-distilled
  25. % with CompatibilityLevel=1.3 .
  26. %
  27. % 2. Objects must be ordered so that any resource be defined before
  28. % its usage.
  29. %
  30. % 3. The PDF file must not include other PDF files.
  31. % Consequently we have a single instance of the PDF reader.
  32. % We use this fact to simplify binding of the routines.
  33. % 4. The PDF root object must always have the object id 1.
  34. % 5. Generations besides 0 are not allowed.
  35. %
  36. % 6. xref must appear after all objects.
  37. %
  38. % Assuming the currentfile isn't positionable.
  39. % As a consequence, the reader fully ignores xref.
  40.  
  41. % ====================== Error handler =======================
  42. % A general error handler prints an error to page.
  43.  
  44. 10 dict begin % A dictionary for local binding
  45.  
  46. /this currentdict def
  47. /y 720 def
  48. /ebuf 200 string def
  49.  
  50. /prnt {
  51.   36 //this /y get moveto //ebuf cvs show
  52.   //this /y 2 copy get 12 sub put
  53. } bind def
  54.  
  55. /newline {
  56.   36 //this /y get moveto
  57.   //this /y 2 copy get 12 sub put
  58. } bind def
  59.  
  60. errordict /handleerror
  61. { systemdict begin
  62.   $error begin
  63.   newerror
  64.   { (%%[ Error handled by opdfread.ps : ) print errorname //ebuf cvs print (; OffendingCommand: )
  65.     print /command load //ebuf cvs print ( ]%%) = flush
  66.     /newerror false store vmstatus pop pop 0 ne
  67.     { grestoreall
  68.     } if
  69.     errorname (VMerror) ne
  70.     { showpage
  71.     } if
  72.     initgraphics
  73.     0 720 moveto
  74.     errorname (VMerror) eq
  75.     { //this /ehsave known
  76.       { clear //this /ehsave get restore 2 vmreclaim
  77.       } if
  78.       vmstatus exch pop exch pop 
  79.     }
  80.     /Courier 12 selectfont
  81.     {
  82.       (ERROR: ) //prnt exec errorname //prnt exec
  83.       (OFFENDING COMMAND: ) //prnt exec
  84.       /command load //prnt exec
  85.       $error /ostack known {
  86.         (%%[STACK:) =
  87.         (STACK:) //prnt exec
  88.         $error /ostack get aload length {
  89.           //newline exec
  90.           dup mark eq {
  91.             (-mark-) dup = show
  92.           } {
  93.             dup type /nametype eq { 
  94.               dup xcheck not {
  95.                 (/) show
  96.                 (/) print
  97.              } if
  98.           } if
  99.           dup = //ebuf cvs show
  100.           } ifelse
  101.         } repeat
  102.       } if
  103.     } ifelse
  104.     (%%]%) =
  105.     //systemdict /showpage get exec
  106.     quit
  107.   } if
  108.   end
  109.   end
  110. } bind readonly put
  111.  
  112. end % A dictionary for local binding
  113.  
  114.  
  115. 50 dict begin
  116.  
  117. % ===================== Debugging =========================================
  118.  
  119. /DefaultSwitch  % <name> DefaultSwitch -
  120. {
  121.   dup where {
  122.     pop pop
  123.   } {
  124.     false def
  125.   } ifelse
  126. } bind def
  127.  
  128. /=string 256 string def
  129.  
  130. /=only {
  131.   //=string cvs print
  132. } bind def
  133.  
  134. /HexDigits (0123456789ABCDEF) readonly def
  135.  
  136. /PrintHex  % <int> PrintHex -
  137. { 8 {
  138.     dup -28 bitshift //HexDigits exch 1 getinterval //=only exec
  139.     4 bitshift
  140.   } repeat
  141.   pop
  142. } bind def
  143.  
  144. /PDFR_DEBUG DefaultSwitch
  145. /PDFR_DUMP DefaultSwitch
  146. /PDFR_STREAM DefaultSwitch
  147. /TTFDEBUG DefaultSwitch
  148. /RotatePages DefaultSwitch
  149. /FitPages DefaultSwitch
  150. /SetPageSize DefaultSwitch
  151.  
  152. /error  %  mark <object> .... error -
  153. { % A stub for a while.
  154.   counttomark 1 sub -1 0 {
  155.     index dup type /arraytype eq { == } { =only } ifelse
  156.   } for
  157.   () =
  158.   cleartomark
  159.   % Assuming ....Undefined is never defined. 
  160.   % Use it to emit an error.
  161.   ....Undefined
  162. } bind def
  163.  
  164. //SetPageSize {
  165.   //RotatePages //FitPages or {
  166.     mark (/RotatePages, /FitPages are not allowed with /SetPageSize) //error exec
  167.   } if
  168. } if
  169.  
  170. % ===================== Utilities =========================================
  171.  
  172. /knownget % <dict> <key> knownget <value> true
  173.           % <dict> <key> knownget false
  174. {
  175.   2 copy known {
  176.     get true
  177.   } {
  178.     pop pop false
  179.   } ifelse
  180. } bind def
  181.  
  182. /IsUpper  % <int> IsUpper <bool>
  183. { dup (A) 0 get ge exch (Z) 0 get le and
  184. } bind def
  185.  
  186. % Copy (recursive) packedarray|array to to global VM
  187. % NOTE: a packedarray will be converted to non-packed (too bad)
  188. /cpa2g {    % <packedarray|array> cpa2g <packedarray|array>
  189.   dup length array    % <src> <dest>
  190.   0 1 2 index length 1 sub {
  191.     % <src> <dest> index
  192.     dup 3 index exch get cp2g
  193.     % <src> <dest> index <globalelement>
  194.     3 copy put pop pop
  195.   } for
  196.   exch pop 
  197. } bind def
  198.  
  199. % Copy (recursive) dict to to global VM
  200. /cpd2g {
  201.   dup length dict exch {
  202.     cp2g 2 index 3 1 roll put
  203.   } forall
  204. } bind def
  205.  
  206. % Copy string to to global VM
  207. /cps2g {    % <string> cps2g <string>
  208.   dup length string copy
  209. } bind def
  210.  
  211. /cp2gprocs 
  212. << /arraytype //cpa2g /dicttype //cpd2g /packedarraytype //cpa2g /stringtype //cps2g >>
  213. def
  214.  
  215. /cp2g {        % <any> cp2g <any>
  216.         % where <any> is array | dict | string | packedarray
  217.         % NOTE: The object must be readable (not executeonly or noaccess)
  218.   dup gcheck not {
  219.     dup //cp2gprocs 1 index type 
  220.     2 copy known {
  221.       get currentglobal 3 1 roll true setglobal exec exch setglobal
  222.       % set the attributes appropriately (we must have 'read' access to get this far)
  223.       1 index wcheck not { readonly } if
  224.       1 index xcheck { cvx } if
  225.       exch pop        % discard original (local) object
  226.     } {
  227.       pop pop    % discard type
  228.     } ifelse
  229.   } if
  230. } bind def
  231.  
  232. % ===================== Work Data =========================================
  233.  
  234. /BlockBuffer 65535 string def % Make it big to load entire TrueType font
  235. /PDFReader currentdict def
  236. /ObjectRegistry 50 array def % may grow later
  237. /CurrentObject null def
  238. /DoneDocumentStructure false def
  239. /GraphicState 20 dict begin
  240.   /InitialTextMatrix matrix def
  241.   /InitialMatrix matrix currentmatrix def
  242. currentdict end def
  243. /TempMatrix matrix def
  244. /GraphicStateStack 20 array def
  245. /GraphicStateStackPointer 0 def
  246. /PDFColorSpaces 50 dict def
  247. /InstalledFonts 50 dict def
  248. /MacRomanEncodingInverse null def
  249.  
  250. % We need some structures in local VM, put then into the userdict :
  251. currentglobal false setglobal
  252. userdict /PDFR_InitialGS gstate put
  253. userdict /PDFR_Patterns 50 dict put
  254. userdict /FuncDataReader 10 dict put
  255. setglobal
  256.  
  257. % ===================== Constants =========================================
  258.  
  259. % The ExtGState elements are composite, thus need to be copied to
  260. % global VM (in case they aren't already global).
  261. /InitialExtGState 20 dict begin
  262.   /BG2 currentblackgeneration cp2g def
  263.   /UCR2 currentundercolorremoval cp2g def
  264.   /TR2 currentglobal false setglobal [ currentcolortransfer ] exch setglobal cp2g def
  265.   /HT currenthalftone cp2g def
  266. currentdict end readonly def
  267.  
  268. /InitialGraphicState 20 dict begin
  269.   /FontSize 0 def
  270.   /CharacterSpacing 0 def
  271.   /TextLeading 0 def
  272.   /TextRenderingMode 0 def
  273.   /WordSpacing 0 def
  274. currentdict end readonly def
  275.  
  276. /SimpleColorSpaceNames 15 dict begin
  277.   /DeviceGray true def
  278.   /DeviceRGB true def
  279.   /DeviceCMYK true def 
  280. currentdict end readonly def
  281.  
  282. /1_24_bitshift_1_sub 1 24 bitshift 1 sub def
  283.  
  284. /ReadFontProcs 10 dict def % Will be filled below.
  285.  
  286. % ===================== Reading PDF objects ===============================
  287.  
  288. /Register % <DefaultDaemon> <id> <obj> Register -
  289. {
  290.   exch dup                                              % d obj id id
  291.   //PDFReader /ObjectRegistry get length ge {
  292.     dup dup 2 idiv add array dup                        % d obj id [n] [n]
  293.     //PDFReader /ObjectRegistry get dup length          % d obj id [n] [n] [o] l
  294.     3 2 roll exch                                       % d obj id [n] [o] [n] l
  295.     0 exch getinterval copy pop                         % d obj id [n]
  296.     //PDFReader exch /ObjectRegistry exch put           % d obj id
  297.   } if
  298.   exch //PDFReader /ObjectRegistry get                  % d id obj r
  299.   3 1 roll                                              % d r id obj
  300.   3 copy pop get                                        % d r id obj e
  301.   dup xcheck {                                          % d r id obj e
  302.     5 4 roll pop                                        % r id obj e
  303.     //PDFR_DEBUG {
  304.       (Have a daemon for ) print 2 index =
  305.     } if
  306.     % We've got a definition daemon, execute it :
  307.     exec
  308.   } {                                                   % d r id obj e
  309.     dup null ne {                                       % d r id obj e
  310.       mark (The object ) 4 index ( already defined : ) 4 index //error exec
  311.     } {
  312.       pop
  313.     } ifelse
  314.     4 3 roll                                            % r id obj d
  315.     % Execute the default daemon :
  316.     exec
  317.   } ifelse                                              % r id obj
  318.   put                                                   %
  319. } bind def
  320.  
  321. /IsRegistered % <id> GetRegistered <bool>
  322. {
  323.   //PDFReader /ObjectRegistry get                       % id r
  324.   dup length                                            % id r l
  325.   2 index le {                                          % id r
  326.     pop pop false
  327.   } {
  328.     exch get                                            % id e
  329.     null ne
  330.   } ifelse
  331. } bind def
  332.  
  333. /GetRegistered % <id> GetRegistered <obj>
  334. {
  335.   //PDFReader /ObjectRegistry get                       % id r
  336.   dup length                                            % id r l
  337.   2 index le {                                          % id r
  338.     exch mark exch (Object ) exch ( isn't defined before needed (1).) //error exec 
  339.   } if
  340.   1 index get                                           % id e
  341.   dup xcheck {
  342.     exch mark exch (Object ) exch ( isn't defined before needed (2).) //error exec 
  343.   } { 
  344.     dup null eq {
  345.       exch mark exch (Object ) exch ( isn't defined before needed (3).) //error exec 
  346.     } if
  347.     exch pop                                            % e
  348.   } ifelse
  349. } bind def
  350.  
  351. /StandardFontNames <<
  352.   /Times-Roman true 
  353.   /Helvetica true
  354.   /Courier true
  355.   /Symbol true
  356.   /Times-Bold true
  357.   /Helvetica-Bold true
  358.   /Courier-Bold true
  359.   /ZapfDingbats true
  360.   /Times-Italic true
  361.   /Helvetica-Oblique true
  362.   /Courier-Oblique true
  363.   /Times-BoldItalic true
  364.   /Helvetica-BoldOblique true
  365.   /Courier-BoldOblique true
  366. >> def
  367.  
  368. /CleanAllResources % - CleanAllResources  -
  369. { //PDFR_DEBUG {
  370.     (CleanAllResources beg) =
  371.   } if
  372.   //PDFReader /ObjectRegistry get
  373.   dup length 0 exch 1 exch 1 sub {                     % R i
  374.     2 copy get dup xcheck {
  375.       % Don't clean a daemon.
  376.       pop pop
  377.     } {
  378.       dup null eq {
  379.         pop pop
  380.       } {
  381.         dup type /dicttype eq { /.Global known } { pop false } ifelse {
  382.           pop
  383.         } {
  384.           //PDFR_DEBUG {
  385.             (Dropping ) print dup =
  386.           } if
  387.           1 index exch /DroppedObject put
  388.         } ifelse
  389.       } ifelse
  390.     } ifelse
  391.   } for
  392.   pop
  393.   FontDirectory length dict begin
  394.   FontDirectory { 
  395.     pop    
  396.     dup //StandardFontNames exch known not {
  397.       dup null def
  398.     } if
  399.     pop
  400.   } forall
  401.   currentdict
  402.   end {
  403.     pop
  404.     //PDFR_DEBUG {
  405.        (Undefining font ) print dup =
  406.     } if
  407.     undefinefont
  408.   } forall
  409.   //PDFR_DEBUG {
  410.     (CleanAllResources end) =
  411.   } if
  412. } bind def
  413.  
  414. /PrintReference % <array> PrintReference <array>
  415. {
  416.   //PDFR_DEBUG {
  417.     ({ ) print
  418.     dup {
  419.       =only ( ) print
  420.     } forall
  421.     ( }) =
  422.   } if
  423. } bind def
  424.  
  425. /R % <id> <gen> R <daemon>
  426. { % Make a reference daemon.
  427.   0 ne {
  428.     exch mark exch (A referred object generation ) exch ( isn't 0.) //error exec
  429.   } if                                                  % id
  430.   [ % <id> proc <obj>
  431.     exch //GetRegistered /exec load 
  432.   ] cvx
  433.   //PrintReference exec
  434. } bind def
  435.  
  436. /IsObjRef %  <any> IsObjRef <bool>
  437.   dup type /arraytype eq {
  438.     dup length 3 eq {
  439.       dup xcheck exch
  440.       dup 0 get type /integertype eq 3 2 roll and exch
  441.       dup 1 get //GetRegistered eq 3 2 roll and exch
  442.       2 get /exec load eq and
  443.     } {
  444.       pop false
  445.     } ifelse
  446.   } {
  447.     pop false
  448.   } ifelse
  449. } bind def
  450.  
  451. /DoNothing 
  452. {
  453. } def
  454.  
  455. /RunTypeDaemon  % <id> <obj> RunTypeDaemon <id> <obj>
  456. {
  457.   dup type /dicttype eq {
  458.     dup /Type //knownget exec {
  459.       //PDFReader /TypeDaemons get exch
  460.       //knownget exec {
  461.         exec
  462.       } if
  463.     } if
  464.   } if
  465. } bind def
  466.  
  467. /obj % <id> <generation> obj <id>
  468. {
  469.   //PDFR_DEBUG {
  470.     (Defining ) print 1 index =only ( ) print dup =only ( obj) =
  471.   } if
  472.   0 ne {
  473.     exch mark exch (An object generation ) exch ( isn't 0.) //error exec
  474.   } if
  475. } bind def
  476.  
  477. /endobj  % <id> <obj> endobj -
  478. {
  479.   //PDFR_DEBUG {
  480.     (endobj ) =
  481.   } if
  482.   dup type /dicttype eq {
  483.     dup /.endobj_daemon //knownget exec {
  484.       //PDFR_DEBUG { (.endobj_daemon for ) print 2 index = } if
  485.       exec
  486.     } if
  487.   } if
  488.   dup type /dicttype eq { dup /ImmediateExec known } { false } ifelse {
  489.     pop pop
  490.   } {
  491.     //PDFR_DEBUG {
  492.       (Storing ) print 1 index =
  493.     } if
  494.     //RunTypeDaemon exec
  495.     //DoNothing 3 1 roll //Register exec
  496.   } ifelse
  497. } bind def
  498.  
  499. /StoreBlock % <buf> StoreBlock -
  500. { % Stores a (encoded) stream data block to the current object.
  501.   //PDFR_DEBUG {
  502.     (StoreBlock ) print //PDFReader /BlockCount get =only (, Length = ) print dup length =
  503.   } if
  504.   dup length string copy
  505.   //PDFReader /BlockCount get exch                      % i s
  506.   //PDFReader /CurrentObject get 3 1 roll               % o i s
  507.   put                                                   %
  508.   //PDFReader /BlockCount get 1 add
  509.   //PDFReader exch /BlockCount exch put
  510. } bind def
  511.  
  512. /CheckLength % <val> CheckNumber <val>
  513. { dup type /integertype ne {
  514.     mark (Object length isn't an integer.) //error exec
  515.   } if
  516. } bind def
  517.  
  518. /ResolveD % <dict> <key> <check> ResolveD <value>
  519. {
  520.   3 copy pop get                                        % <> key {} e
  521.   dup //IsObjRef exec {
  522.     % We've got a reference daemon, execute it :
  523.     //PDFR_DEBUG {
  524.       (Resolving ) print //PrintReference exec
  525.     } if
  526.     exec                                                % <> key {} val
  527.     exch exec                                           % <> key val
  528.   } {
  529.     exch pop
  530.   } ifelse
  531.   dup 4 1 roll                                          % val <> key val
  532.   put                                                   % val
  533. } bind def
  534.  
  535. /ResolveA   % <array> <index> <check> ResolveA <value>
  536. { 2 index 2 index get
  537.   dup //IsObjRef exec {
  538.     exec
  539.     exch exec
  540.     3 copy put
  541.   } {
  542.     exch pop
  543.   } ifelse
  544.   exch pop exch pop
  545. } bind def
  546.  
  547. /StoreStream  % <id> <obj> StoreStream <id> <obj>
  548. { % Stores a (encoded) data stream copy to the current object.
  549.   dup //PDFReader exch /CurrentObject exch put          % id obj
  550.   //PDFReader /BlockCount 0 put
  551.   dup /Length //CheckLength //ResolveD exec             % id obj l
  552.   //PDFR_DEBUG {
  553.     (StoreStream Length = ) print dup =
  554.   } if
  555.   currentfile exch () /SubFileDecode filter             % id obj file
  556.   { dup //BlockBuffer readstring {                      % id obj file buf
  557.       //StoreBlock exec
  558.     } {
  559.       //StoreBlock exec
  560.       exit
  561.     } ifelse                                            % id obj file
  562.   } loop
  563.   pop                                                   % id obj
  564.   //PDFReader /CurrentObject null put
  565.   //PDFR_DEBUG {
  566.     (StoreStream end.) =
  567.   } if
  568. } bind def
  569.  
  570. /MakeStreamDumper % <file> MakeStreamDumper <file>
  571. { % Debug purpose only.
  572.   //PDFR_DEBUG {
  573.     (MakeStreamDumper beg.) =
  574.   } if
  575.   currentglobal exch dup gcheck setglobal
  576.   [ exch                      % f
  577.     1 dict dup /c 0 put exch  % d f
  578.     1024 string               % d f s
  579.     { readstring pop          % d s
  580.       (StreamDumper ) print 1 index /c get =string cvs print ( ) print 
  581.       dup length =string cvs print ( <) print dup print (>\n) print
  582.       dup length              % d s l
  583.       3 2 roll                % s l d
  584.       dup /c get              % s l d c
  585.       3 2 roll                % s d c l
  586.       add /c exch put         % s
  587.     } /exec load    
  588.   ] 
  589.   cvx 0 () /SubFileDecode filter
  590.   exch setglobal
  591.   //PDFR_DEBUG {
  592.     (MakeStreamDumper end.) =
  593.   } if
  594. } bind def
  595.  
  596. /ShortFilterNames 15 dict begin
  597.   /AHx /ASCIIHexDecode def
  598.   /A85 /ASCII85Decode def
  599.   /LZW /LZWDecode def
  600.   /Fl  /FlateDecode def
  601.   /RL  /RunLengthDecode def
  602.   /CCF /CCITTFaxDecode def
  603.   /DCT /DCTDecode def
  604. currentdict end readonly def
  605.  
  606. /AppendFilters  % <file> <dict> AppendFilters <file>
  607. {
  608.   //PDFR_DEBUG {
  609.     (AppendFilters beg.) =
  610.   } if
  611.   dup 3 1 roll                                      % d f d
  612.   /Filter //knownget exec {                         % d f F
  613.     dup type /nametype eq {                         % d f /F
  614.       dup //ShortFilterNames exch //knownget exec {
  615.         exch pop
  616.       } if
  617.       2 index /DecodeParms //knownget exec {        % d f p /F
  618.         exch
  619.       } if
  620.       filter                                        % d f'
  621.     } {                                             % d f []
  622.       dup 0 exch 1 exch length 1 sub {              % d f [] i
  623.         2 copy get                                  % d f [] i /F
  624.         dup //ShortFilterNames exch //knownget exec {
  625.           exch pop
  626.         } if
  627.         3 1 roll                                    % d f /F [] i
  628.         4 index /DecodeParms //knownget exec {      % d f /F [] i DP
  629.           exch get                                  % d f /F [] dp
  630.         } {                                         % d f /F [] i
  631.           pop null                                  % d f /F [] dp
  632.         } ifelse
  633.         dup null eq {                               % d f /F [] dp
  634.           pop 3 1 roll filter exch                  % d f' []
  635.         } {                                         % d f /F [] dp
  636.           3 1 roll                                  % d f dp /F []
  637.           4 1 roll filter exch                      % d f' []
  638.         } ifelse
  639.       } for
  640.       pop                                           % d f'
  641.     } ifelse
  642.     //PDFR_DEBUG //PDFR_DUMP and  {
  643.       //MakeStreamDumper exec
  644.     } if
  645.   } if
  646.   exch pop
  647.   //PDFR_DEBUG {
  648.     (AppendFilters end.) =
  649.   } if
  650. } bind def
  651.  
  652. /ExecuteStream  % <id> <obj> ExecuteStream <id> <obj>
  653. { % Executes a (encoded) data stream.
  654.   dup //PDFReader exch /CurrentObject exch put          % id obj
  655.   dup /Length //CheckLength //ResolveD exec             % id obj l
  656.   //PDFR_DEBUG {
  657.     (ExecuteStream id = ) print 2 index =only ( Length = ) print dup =
  658.   } if
  659.   //PDFReader /InitialGraphicState get 
  660.   //PDFReader /GraphicState get copy pop
  661.   //PDFReader /Operators get begin
  662.   % currentfile exch () /SubFileDecode filter           % id obj file
  663.   % We would like to use the code above, 
  664.   % but HP LaserJet 1320 continues parsing after the byte count exceeds.
  665.   pop currentfile 0 (endstream) /SubFileDecode filter   % id obj file
  666.   1 index //AppendFilters exec
  667.   cvx mark exch                                         % id obj mark file
  668.   exec
  669.   counttomark 0 ne {
  670.     mark (Data left on ostack after an immediate stream execution.) //error exec
  671.   } if
  672.   cleartomark                                           % id obj
  673.   end % Operators
  674.   //PDFR_DEBUG {
  675.     (ExecuteStream end.) =
  676.   } if
  677.   //PDFReader /CurrentObject null put
  678.   dup /IsPage known {
  679.     dup /Context get /NumCopies //knownget exec {
  680.       1 sub {
  681.         copypage
  682.       } repeat
  683.     } if
  684.     showpage
  685.   } if
  686. } bind def
  687.  
  688. /stream  % <id> <obj> stream <id> <obj>
  689.   //PDFR_DEBUG {
  690.     1 index =only ( stream) =
  691.   } if                                                  % id obj
  692.   % Run the object definition daemon, if exists :
  693.   //PDFReader /ObjectRegistry get dup length 3 index    % id obj r l id
  694.   gt {                                                  % id obj r
  695.     2 index get 
  696.     dup xcheck {
  697.       exec
  698.       % Disable the daemon :
  699.       //PDFReader /ObjectRegistry get 2 index null put
  700.     } {
  701.       pop
  702.     } ifelse
  703.   } {
  704.     pop
  705.   } ifelse                                              % id obj
  706.   dup /ImmediateExec known {
  707.     dup /GlobalExec //knownget exec {
  708.       currentglobal 4 1 roll
  709.       setglobal
  710.       //ExecuteStream exec
  711.       3 2 roll setglobal
  712.     } {
  713.       //ExecuteStream exec
  714.     } ifelse
  715.   } {
  716.     //StoreStream exec
  717.   } ifelse
  718.   dup /.CleanResources //knownget exec {
  719.     /All eq {
  720.       //CleanAllResources exec
  721.     } if
  722.   } if
  723. } bind def
  724.  
  725. /HookFont % <id> <obj> <font_descriptor> HookFont <id> <obj>
  726.     //PDFR_DEBUG {
  727.       (Loaded the font ) print dup /FontName get =
  728.     } if
  729.     {
  730.       dup /FontFileType get dup /Type1 eq exch /MMType1 eq or {  % id obj fd
  731.         % We assume that the Type 1 font has same name with no prefix
  732.         % due to pdfwrite specifics.
  733.         % We use it to find the font after it is defined.
  734.         % We could redefine 'definefont' for hooking the font, 
  735.         % but we don't think that it could be guaranteedly portable : 
  736.         % a 3d party PS interpreter may set a special context 
  737.         % when running the font file.
  738.         % Note that this mechanizm does not depend on the
  739.         % font name uniquity, because the last 'definefont'
  740.         % is only important.
  741.         dup /FontName get                               % id obj fd fn
  742.         //PDFReader /RemoveFontNamePrefix get exec 
  743.         findfont                                        % id obj fd g f
  744.         exit
  745.       } if
  746.       dup /FontFileType get /TrueType eq {              % id obj fd
  747.         //PDFReader /MakeType42 get exec
  748.         //PDFR_DEBUG {
  749.           (Font dict <<) =
  750.           dup {
  751.             1 index /sfnts eq {
  752.               exch pop
  753.               (/sfnts [) print
  754.               {
  755.                 (-string\() print length //=only exec (\)- ) =
  756.               } forall
  757.               (]) =
  758.             } {
  759.               exch //=only exec ( ) print ==
  760.             } ifelse
  761.           } forall
  762.           (>>) =
  763.         } if
  764.         dup /FontName get exch definefont
  765.         exit
  766.       } if
  767.       mark (FontHook has no proc for ) 2 index /FontFileType get //error exec
  768.     } loop
  769.     /Font exch put                                      % id obj
  770. } bind def
  771.  
  772. /endstream % <id> <obj> endstream <id> <obj>
  773. } bind def
  774.  
  775. /xref % - xref -
  776.   //PDFR_DEBUG {
  777.     (xref) =
  778.     //PDFR_DUMP {
  779.       //PDFReader /ObjectRegistry get ==
  780.     } if
  781.   } if
  782.   end % The procset
  783.   count 0 ne {
  784.     mark (Excessive data on estack at the end of the interpretation.) //error exec
  785.   } if
  786.   currentfile 1 (%%EOF) /SubFileDecode filter
  787.   flushfile
  788.   cleardictstack
  789. } bind def
  790.  
  791. % ===================== Restoring the PDF Document Structure ===============
  792.  
  793. /ResolveDict  % <dict> /ResolveDict -
  794. { dup {                                                 % d key val
  795.     pop 1 index exch                                    % d cp key
  796.     //DoNothing //ResolveD exec                         % d obj
  797.     pop                                                 % d
  798.   } forall
  799.   pop                                                   %
  800. } bind def
  801.  
  802. /SetupPageView  % <obj> SetupPageView -
  803. {
  804.   //PDFR_DEBUG {
  805.     (SetupPageView beg) =
  806.   } if
  807.   //GraphicState /InitialMatrix get setmatrix
  808.   /MediaBox get aload pop                               % bx0 by0 bx1 by1
  809.   3 index neg 3 index neg translate % Temporary move to origin
  810.   3 -1 roll sub 3 1 roll exch sub exch                  % bw bh
  811.   userdict  /.HWMargins //knownget exec {
  812.     aload pop
  813.   } {
  814.     currentpagedevice /.HWMargins //knownget exec {
  815.       aload pop
  816.     } {
  817.       0 0 0 0
  818.     } ifelse
  819.   } ifelse
  820.   currentpagedevice /PageSize get aload pop
  821.   3 -1 roll sub 3 1 roll exch sub exch                  % bw bh px0 py0 px1 py1
  822.   exch 3 index sub exch 3 index sub                     % bw bh px0 py0 pw ph
  823.   //SetPageSize {
  824.     //PDFR_DEBUG {
  825.       (Setting page size to ) print 1 index //=only exec ( ) print dup =
  826.     } if
  827.     pop pop 3 index 3 index 2 copy                      % bw bh px0 py0 bw bh bw bh
  828.     currentglobal false setglobal 3 1 roll              % bw bh px0 py0 bw bh bool bw bh
  829.     2 array astore                                      % bw bh px0 py0 bw bh bool []
  830.     << exch /PageSize exch >> setpagedevice             % bw bh px0 py0 bw bh bool
  831.     userdict /PDFR_InitialGS gstate put
  832.     setglobal                                           % bw bh px0 py0 bw bh
  833.   } if
  834.   //RotatePages {
  835.     2 copy gt 6 index 6 index gt ne {
  836.       % a rotation is useful except it fits with no rotation.
  837.       1 index 5 index le 1 index 5 index le and not
  838.     } {
  839.       false
  840.     } ifelse
  841.   } {
  842.     false
  843.   } ifelse
  844.   { //FitPages {
  845.       1 index 5 index div 1 index 7 index div           % bw bh px0 py0 pw ph sx sy
  846.       2 copy gt {
  847.         exch
  848.       } if
  849.       pop dup scale                                     % bw bh px0 py0 pw ph
  850.     } if
  851.     90 rotate
  852.     0 5 index neg translate
  853.   } {
  854.     //FitPages {
  855.       1 index 6 index div 1 index 6 index div           % bw bh px0 py0 pw ph sx sy
  856.       2 copy gt {
  857.         exch
  858.       } if
  859.       pop dup scale                                     % bw bh px0 py0 pw ph
  860.     } if
  861.   } ifelse                                               
  862.   pop pop                                               % bw bh px0 py0
  863.   translate                                             % bw bh
  864.   pop pop                                               %
  865.   //PDFR_DEBUG {
  866.     (SetupPageView end) =
  867.   } if
  868. } bind def
  869.  
  870. /PageContentsDaemon % <id> <obj> <node> PageContentsDaemon <id> <obj>
  871. { % Note: an excessive operand from a prebond procedure.
  872.   //PDFR_DEBUG {
  873.     (Executing PageContentsDaemon for ) print 2 index =
  874.   } if                                                  % id obj node
  875.   1 index exch /Context exch put                        % id obj
  876.   dup /ImmediateExec true put
  877.   dup /IsPage true put
  878.   dup /Context get //SetupPageView exec
  879. } bind def
  880.  
  881. /FontFileDaemon % <id> <obj> <font_descriptor> FontFileDaemon <id> <obj>
  882. { % Note: an excessive operand from a prebond procedure.
  883.   //PDFR_DEBUG {
  884.     (Executing FontFileDaemon for ) print 2 index =
  885.   } if
  886.   % We need any font resource that refers this descriptor
  887.   % to know the font type. Assuming that FontDescriptorDaemon
  888.   % provided FontFileType.
  889.   dup /FontFileType get                                 % id obj fd ft
  890.   2 index exch                                          % id obj fd obj ft
  891.   dup //ReadFontProcs exch //knownget exec {            % id obj fd obj ft proc
  892.      exch pop exec                                      % id obj fd
  893.   } {
  894.     mark (FontFile reader for ) 2 index ( isn't implemented yet.) //error exec
  895.   } ifelse
  896.   //PDFR_DEBUG {
  897.     (FontFileDaemon end) =
  898.   } if                                                  % id obj fd
  899.   pop
  900. } bind def
  901.  
  902. /FontDescriptorDaemon % <id> <obj> <font_resource> FontDescriptorDaemon <id> <obj>
  903. { % Note: an excessive operand from a prebond procedure.
  904.   //PDFR_DEBUG {
  905.     (Executing FontDescriptorDaemon for ) print 2 index =
  906.   } if                                                  % id obj fr
  907.   %HACK BEG assuming an own font for each font descriptor
  908.           % to provide an access to PDFEncoding
  909.           % from MakeType42, ComposeCharStrings.
  910.     2 copy /FontResource exch put
  911.   %HACK END
  912.   /Subtype get 1 index exch /FontFileType exch put
  913. } bind def
  914.  
  915. /UnPDFEscape {    % <namepdf> UnPDFEscape <nameps>
  916.   dup dup length string cvs                    % /namepdf (name)
  917.   dup (#) search {
  918.     % name contains PDF-style escapes ("#hh") that need to be removed
  919.     {                                                % ... (po..st) (#) (pre)
  920.       pop                                            % ... (po..st) (#)
  921.       (16#--) 2 index 0 2 getinterval                % ... (po..st) (#) (16#--) (po)
  922.       1 index 3 2 getinterval copy pop                % ... (po..st) (#) (16#po)
  923.       cvi                                            % ... (po..st) (#) 16#po
  924.       0 exch put                                    % ... (po..st); 16#po patched into (#)
  925.       0                                                % ... (po..st) 0
  926.       1 index 2 1 index length 2 sub getinterval    % ... (po..st) 0 (..st)
  927.       3 copy putinterval                            % ... (..stst) 0 (XXst)
  928.       length                                        % ... (..stst) 0 LEN_OF_(po..st)-2
  929.       3 copy exch put                                % ... (..st\0t) 0 LEN_OF_(po..st)-2
  930.       getinterval                                    % ... (..st), stored at begining of old (po..st)
  931.       (#) search not {
  932.     pop exit                    % /namepdf (nameps\0..)
  933.       } if
  934.     } loop
  935.     % we have a '\0' marker (not allowed in PDF names) after all usefull characters
  936.     (\0) search pop exch pop exch pop
  937.     cvn
  938.     exch pop
  939.   } {
  940.     pop pop
  941.   } ifelse
  942. } bind def
  943.  
  944. /TypeDaemons <<  % <id> <obj> proc <id> <obj>
  945.   /Page 
  946.   { //PDFR_DEBUG {
  947.       (Recognized a page.) =
  948.     } if
  949.     dup /Contents //knownget exec {                     % id obj c
  950.       0 get //DoNothing exch                            % id obj dn id1
  951.       [ % <id> <obj> proc <id> <obj>
  952.         3 index //PageContentsDaemon /exec load
  953.       ] cvx                                             % id obj {}
  954.       //Register exec                                   % id obj
  955.     } {
  956.       (fixme: page with no Contents won't be printed.) =
  957.     } ifelse
  958.   } bind
  959.   /FontDescriptor
  960.   { //PDFR_DEBUG {
  961.       (Recognized a font descriptor.) =
  962.     } if
  963.     dup /FontName //knownget exec {
  964.     1 index /FontName 3 -1 roll //UnPDFEscape exec put
  965.     } if
  966.     dup dup /FontFile known {/FontFile} {/FontFile2} ifelse 
  967.     //knownget exec {                                 % id obj ff
  968.       0 get //DoNothing exch                          % id obj dn id1
  969.       [ % <id> <obj> proc <id> <obj>
  970.         3 index //FontFileDaemon /exec load
  971.       ] cvx                                           % id obj {}
  972.       //Register exec                                 % id obj
  973.     } {
  974.       % FontFile3 are not implemented yet.
  975.       (Font descriptor ) print 1 index =only ( has no FontFile.) =
  976.     } ifelse
  977.   } bind
  978.   /Font
  979.   { //PDFR_DEBUG {
  980.       (Recognized a font resource.) =
  981.     } if
  982.     dup /BaseFont //knownget exec {
  983.       //UnPDFEscape exec 2 copy /BaseFont exch put
  984.       % cache the installed font (if any) before replacing it.
  985.       //PDFReader /RemoveFontNamePrefix get exec
  986.       currentglobal exch % A hack against HP LaserJet 1320 bug :
  987.                          % It sets the local allocation mode
  988.                          % when 'resourcestatus' fails.
  989.       dup /Font resourcestatus {
  990.         pop pop
  991.         //PDFReader /GetInstalledFont get exec pop
  992.       } {
  993.         pop
  994.       } ifelse
  995.       setglobal
  996.     } if
  997.     dup /FontDescriptor //knownget exec {               % id obj fd
  998.       0 get                                             % id obj id1
  999.       dup //IsRegistered exec {                         % id obj id1
  1000.         //PDFR_DEBUG {
  1001.           (already registered ) print dup =
  1002.         } if
  1003.         pop
  1004.       } {
  1005.         //DoNothing exch                                % id obj dn id1
  1006.         [ % <id> <obj> proc <id> <obj>
  1007.           3 index //FontDescriptorDaemon /exec load
  1008.         ] cvx                                           % id obj {}
  1009.        //Register exec                                  % id obj
  1010.       } ifelse
  1011.     } if
  1012.   } bind
  1013. >> def
  1014.  
  1015. /MakeStreamReader % <obj> MakeStreamReader <file>
  1016. { dup
  1017.   [ 
  1018.     exch
  1019.     //PDFR_DEBUG {
  1020.       (Stream proc )
  1021.       /print load
  1022.       //PDFR_STREAM {
  1023.         (<)
  1024.         /print load
  1025.       } if
  1026.     } if
  1027.     1 dict dup /i -1 put
  1028.     /dup load
  1029.     /i 
  1030.     /get load
  1031.     1
  1032.     /add load
  1033.     /dup load
  1034.     3 
  1035.     1 
  1036.     /roll load
  1037.     /i
  1038.     /exch load
  1039.     /put load
  1040.     //knownget
  1041.     /exec load 
  1042.     /not load
  1043.     { () }
  1044.     /if load
  1045.     //PDFR_DEBUG {
  1046.       //PDFR_STREAM {
  1047.         /dup load
  1048.         /print load
  1049.         (>)
  1050.         /print load
  1051.       } if
  1052.       ( end of stream proc.\n)
  1053.       /print load
  1054.     } if
  1055.   ] cvx
  1056.   //PDFR_DEBUG {
  1057.     (Stream reader ) print dup ==
  1058.   } if
  1059.   0 () /SubFileDecode filter
  1060.   exch //AppendFilters exec
  1061. } bind def
  1062.  
  1063. /RunDelayedStream % <stream_obj> RunDelayedStream -
  1064. {
  1065.   //MakeStreamReader exec                                       % file
  1066.   mark exch
  1067.   cvx exec                                                      %
  1068.   counttomark 0 ne {
  1069.     mark (Data left on ostack after a delayed stream execution.) //error exec
  1070.   } if
  1071.   cleartomark
  1072. } bind def
  1073.  
  1074. % ===================== Font Management ======================
  1075.  
  1076. //ReadFontProcs begin
  1077.   /Type1   % <font_descriptor> <FontFile_object> Type1 <font_descriptor>
  1078.   { //PDFR_DEBUG {
  1079.       (ReadFontProcs.Type1) =
  1080.     } if
  1081.     dup /.endobj_daemon [ 4 index //HookFont /exec load ] cvx put
  1082.     dup /ImmediateExec true put
  1083.     /GlobalExec true put
  1084.   } bind def
  1085.   /MMType1 //Type1 def
  1086.   /TrueType   % <font_descriptor> <FontFile_object> TrueType <font_descriptor>
  1087.   { //PDFR_DEBUG {
  1088.       (ReadFontProcs.TrueType) =
  1089.     } if
  1090.     dup /.endobj_daemon [ 4 index //HookFont /exec load ] cvx put
  1091.     pop
  1092.   } bind def
  1093. end
  1094.  
  1095. % A working dictionary to hold items related to reading a TrueType font
  1096. % and converting into a type 42 font, especially regarding creating the sfnts
  1097. % array of strings, and ensuring strings are split on table boundaries and
  1098. % for the glyf table, on glyph boundaries.
  1099. %
  1100. /.opdloadttfontdict 50 dict def
  1101. .opdloadttfontdict begin 
  1102.  
  1103. /maxstring 65400 def    % less than the maximum length of a PostScript string,
  1104.                         % must be a multiple of 4 (for hmtx / loca / vmtx)
  1105. end
  1106.  
  1107. % Uses an insertion sort to sort the contents of an array,
  1108. % the sorted array is returned. Takes the array to sort and a 
  1109. % comparison procedure. The comparison procedure must take two
  1110. % arguments, and return a boolean. The return value should be
  1111. % false if arguments incorrectly ordered, true if they are 
  1112. % already in the correct order.
  1113. %
  1114. % [Array to sort] {comparisaon proc} InsertionSort [Sorted array]
  1115. %
  1116. /.InsertionSort
  1117. {
  1118.     /CompareProc exch def
  1119.     /Array exch def
  1120.     1 1 Array length 1 sub
  1121.     {
  1122.         /Ix exch def
  1123.         /Value1 Array Ix get def
  1124.  
  1125.         /Jx Ix 1 sub def
  1126.         {
  1127.             Jx 0 lt {
  1128.                 exit
  1129.             } if
  1130.             /Value2 Array Jx get def
  1131.             Value1 Value2 CompareProc {
  1132.                 exit
  1133.             } if
  1134.             
  1135.             Array Jx 1 add Value2 put
  1136.             /Jx Jx 1 sub def
  1137.         } loop
  1138.         Array Jx 1 add Value1 put
  1139.     } for
  1140.     Array
  1141. } bind def
  1142.  
  1143. %
  1144. % Utility rourtines to insert a TrueType data type
  1145. %
  1146. % <string> <index> <integer> putu16 -
  1147. /putu16 {
  1148.   3 copy -8 bitshift put
  1149.   exch 1 add exch 16#ff and put
  1150. } bind def
  1151. % <string> <index> <integer> putu32 -
  1152. /putu32 {
  1153.   3 copy -16 bitshift putu16
  1154.   exch 2 add exch 16#ffff and putu16
  1155. } bind def
  1156.  
  1157. %
  1158. % Utility routines to read TrueType table data, returning
  1159. % either a string or an array of strings depending on the 
  1160. % table length.
  1161. %
  1162.  
  1163. % Read a table as a single string.
  1164. % <file> <length> .readtable <string>
  1165. /.readtable {
  1166.   dup dup 1 and add string
  1167.         % Stack: f len str
  1168.   dup 0 4 -1 roll getinterval
  1169.         % Stack: f str str1
  1170.     % Because of the absurd PostScript specification that gives an
  1171.     % error for reading into an empty string, we have to check for
  1172.     % this explicitly here.
  1173.   3 -1 roll exch
  1174.   dup () ne { readstring } if pop pop
  1175. } bind def
  1176.  
  1177. % Read a big table (one that may exceed 64K).
  1178. % <file> <length> .readbigtable <string[s]>
  1179. /.readbigtable {
  1180.   dup maxstring lt {
  1181.     .readtable
  1182.   } {
  1183.     currentuserparams /VMReclaim get -2 vmreclaim
  1184.     [ 4 2 roll {
  1185.         % Stack: mark ... f left
  1186.       dup maxstring le { exit } if
  1187.       1 index maxstring string readstring pop 3 1 roll maxstring sub
  1188.     } loop .readtable ]
  1189.     exch vmreclaim
  1190.   } ifelse
  1191. } bind def
  1192.  
  1193. % ReadTTF reads the tables and so on from a TreuType font into memory
  1194. % so that they are available for later processing.
  1195. %
  1196. % <filename> ReadTTF - 
  1197. %
  1198. /ReadTTF
  1199. {
  1200.   .opdloadttfontdict begin
  1201.   /TTFontFile exch def
  1202.   
  1203.   % Table directory:
  1204.   %  version       -    fixed (4 bytes)
  1205.   %  numTables     -    USHORT (2 bytes)
  1206.   %  searchRange   -    USHORT (2 bytes)
  1207.   %  entrySelector -    USHORT (2 bytes)
  1208.   % Read Table
  1209.   /TableDir TTFontFile 12 string readstring pop def
  1210.   
  1211.   % There are numTables table directory entries:
  1212.   %   tag          -    ULONG (4 bytes)
  1213.   %   checkSum     -    ULONG (4 bytes)
  1214.   %   offset       -    ULONG (4 bytes)
  1215.   %   length       -   ULONG (4 bytes)
  1216.   % Read entries
  1217.   /tables TTFontFile TableDir 4 getu16 16 mul string readstring pop def
  1218.   
  1219.   % Create dictionary to store directory entries.
  1220.   /tabarray tables length 16 idiv array def
  1221.   
  1222.   % Check version for TrueType collection
  1223.   TableDir 0 4 getinterval (ttcf) eq {
  1224.       QUIET not { (Can't handle TrueType font Collections.) = } if
  1225.       /.loadttfonttables cvx /invalidfont signalerror
  1226.   } {
  1227.     % There are ((length of tables string) / 16) Table directory entries
  1228.     % Get and store each in turn
  1229.     0 16 tables length 1 sub {
  1230.       % Get each directory entry as a 16-byte string
  1231.       dup                                       % index index
  1232.       tables exch 16 getinterval                % index (string)
  1233.         exch 16 div cvi exch                    % index/16 (string)
  1234.       tabarray  3 1 roll put
  1235.     } for 
  1236.   } ifelse
  1237.   
  1238.   % We need the tables in the order they occur in the file, so sort
  1239.   % by 'offset'.
  1240.   tabarray { exch 8 getu32 exch 8 getu32 gt} .InsertionSort pop
  1241.  
  1242.   % Now we read the content of each table in turn. If the table is < 64K
  1243.   % then we store it in a single string. If its more, we store it in an 
  1244.   % array of strings. The table contents are stored in 'tabs' in the same
  1245.   % order as they are read from the file, as per the sorted array 'tabarray'.
  1246.   /Read TableDir length tables length add def
  1247.   /tabs [
  1248.     tabarray {
  1249.       % Get offset (from start of file) of next table
  1250.       dup 8 getu32                                        % () offset
  1251.       % Subtract amount read so far 
  1252.       Read sub                                            % () offset-Read
  1253.       dup 0 gt {
  1254.       % Read and discard any extra padding bytes          % () offset-Read
  1255.       dup string TTFontFile exch readstring pop pop       % () offset-Read 
  1256.       % Update bytes read
  1257.       Read add /Read exch def                             % ()
  1258.       } {
  1259.        pop                                                % ()
  1260.       } ifelse
  1261.       % Find length of this table and add it to bytes read
  1262.       12 getu32                                           % () tablelength
  1263.       dup Read add                                        % () tablelength tablelength+Read
  1264.       /Read exch def                                      % () tablelength
  1265.       TTFontFile exch .readbigtable                            
  1266.     } forall
  1267.   ] def
  1268.   end % .opdloadttfontdict  
  1269. } bind def
  1270.  
  1271. % GetLocaType finds the head table in tabarray, which gives
  1272. % an index into the 'tabs' array where the data is stored.
  1273. % From that data we extract the loca type (short or long).
  1274. %
  1275. % - GetLocaType -
  1276. %
  1277. /GetLocaType
  1278. {
  1279.   0 1 tabarray length 1 sub{
  1280.                                   % control-variable
  1281.     dup tabarray exch get         % control-variable ()
  1282.     0 4 getinterval (head) eq{    % control-variable bool
  1283.       tabs exch get               % ()
  1284.       50 gets16
  1285.       /LocaType exch def 
  1286.       exit
  1287.     } {
  1288.       pop % control variable      % -
  1289.     } ifelse
  1290.   } for
  1291. } bind def
  1292.  
  1293. % GetNumGlyphs finds the maxp table in tabarray, which gives
  1294. % an index into the 'tabs' array where the data is stored.
  1295. % From that data we extract the number of glyphs in the font.
  1296. %
  1297. % - GetNumGlyphs -
  1298. %
  1299. /GetNumGlyphs
  1300. {
  1301.   0 1 tabarray length 1 sub{
  1302.                                   % control-variable
  1303.     dup tabarray exch get         % control-variable ()
  1304.     0 4 getinterval (maxp) eq{    % control-variable bool
  1305.       % Get the maxp string 
  1306.       % from the tabs array
  1307.       tabs exch get               % ()
  1308.       4 getu16                    % int
  1309.       /NumGlyphs exch def
  1310.       exit                        % int
  1311.     } {
  1312.       pop % control variable      % -
  1313.     } ifelse
  1314.   } for
  1315. } bind def
  1316.  
  1317. % StringtoLoca takes a string, and an index in to an array
  1318. % where the loca results should be stored from. It reads 
  1319. % along the string getting either 2-byte or 4-byte values
  1320. % (depends on loca type) and stores them in the array at
  1321. % successive locations. Leaves the next unused location
  1322. % on the stack at end (easy to process multiple strings).
  1323. %
  1324. % string ArrayIndex StringToLoca  ArrayIndex
  1325. %
  1326. /StringToLoca
  1327. {    
  1328.   /LocaIndex exch def                        % ()
  1329.   /StringOffset 0 def                        % ()
  1330.   {    
  1331.     dup length StringOffset gt {             % () 
  1332.       dup                                    % ()
  1333.       LocaType 1 eq{
  1334.         StringOffset getu32                  % () loca
  1335.         LocaArray LocaIndex 3 -1 roll put    % ()
  1336.         /LocaIndex LocaIndex 1 add def       % ()
  1337.         /StringOffset StringOffset 4 add     % ()
  1338.         def
  1339.       } {
  1340.         dup                                  % () loca
  1341.         StringOffset getu16                  % ()
  1342.         LocaArray LocaIndex 3 -1 roll put    % ()
  1343.         /LocaIndex LocaIndex 1 add def       % () 
  1344.         /StringOffset StringOffset 4 add     % ()
  1345.         def
  1346.       } ifelse
  1347.     }{                                       % ()
  1348.       pop                                    % -
  1349.       LocaIndex                              % return index
  1350.       exit
  1351.     }ifelse
  1352.   } loop
  1353. } bind def
  1354.  
  1355. % GetSortedLoca reads the loca table, and sorts it by offset
  1356. % this is so that we can walk up the array looking for an approporiate
  1357. % place to split strings. The result is stored in LocArray
  1358. %
  1359. % - GetSortedLoca -
  1360. %
  1361. /GetSortedLoca
  1362. {
  1363.   NumGlyphs 1 add array /LocaArray exch def
  1364.   
  1365.   % Get the loca table
  1366.   0 1 tabarray length 1 sub{
  1367.                                  % control-variable
  1368.     dup tabarray exch get        % control-variable ()
  1369.     0 4 getinterval (loca) eq{   % control-variable bool
  1370.       % Get the loca string 
  1371.       % from the tabs array
  1372.       tabs exch get              % ()
  1373.       exit
  1374.     } {
  1375.       pop % control variable     % -
  1376.     } ifelse
  1377.   } for
  1378.  
  1379.   % If its a single string handle the easy way
  1380.   dup type /stringtype eq {
  1381.     0 StringToLoca pop
  1382.   }{
  1383.     % Otherwise its an array, process each string in the array
  1384.     0 exch % Starting LocaArray index
  1385.     {
  1386.       exch StringToLoca
  1387.     }forall
  1388.     pop % final LocaArray index
  1389.   }ifelse
  1390.  
  1391.   % Now we've read all the locations, sort them so 
  1392.   % we can figure out where to break the strings
  1393.   LocaArray {gt} .InsertionSort pop
  1394. } bind def
  1395.  
  1396. % Updates internal storage with a new string from the
  1397. % GlyfArray
  1398. % - GetWorkingString -
  1399. /GetWorkingString
  1400. {
  1401.   WorkString 0
  1402.   GlyfArray GlyfStringIndex get
  1403.   putinterval
  1404.   % Update the available bytes
  1405.   /WorkBytes GlyfArray GlyfStringIndex get length def
  1406.   % Set index to get data from next string in array
  1407.   /GlyfStringIndex GlyfStringIndex 1 add def
  1408. } bind def
  1409.  
  1410. % Returns a string with the requested number of bytes taken
  1411. % from WorkingString. There must be enough data in WorkingString to
  1412. % satisfy the request
  1413. %
  1414. /GetWorkingBytes
  1415. {
  1416.   /BytesToRead exch def
  1417.   % Get 'BytesToRead' bytes from working store
  1418.   WorkString 0 BytesToRead getinterval
  1419.   dup length string copy
  1420.   % Get remaining bytes from working store
  1421.   WorkString BytesToRead WorkBytes BytesToRead sub getinterval
  1422.   dup length string copy
  1423.   % replace first 'n' bytes of working store with unread bytes
  1424.   WorkString 0 3 -1 roll putinterval
  1425.   % Subtract bytes read from bytes available
  1426.   /WorkBytes WorkBytes BytesToRead sub def
  1427. } bind def
  1428.  
  1429. % Read 'int' bytes from GlyfArray strings, return string composed
  1430. % of those bytes
  1431. %
  1432. % int GetGlyfBytes string
  1433. /GetGlyfBytes
  1434. {
  1435.   /ToRead exch def
  1436.   
  1437.   % If we have no available data, get soem from the array of
  1438.   % glyf strings
  1439.   WorkBytes 0 eq {
  1440.     GetWorkingString
  1441.   } if
  1442.  
  1443.   WorkBytes ToRead ge {
  1444.     ToRead string dup 0
  1445.     ToRead GetWorkingBytes putinterval
  1446.   }{
  1447.     % Create a string sized to hold the target data
  1448.     ToRead string
  1449.     % Get remaining stored bytes, and put at the start
  1450.     % of the string
  1451.     dup 
  1452.     % Start of string
  1453.     0 
  1454.     % Get remaining bytes
  1455.     WorkString 0 WorkBytes getinterval 
  1456.     % store at start of output string
  1457.     putinterval
  1458.     
  1459.     dup
  1460.     % Location in output to store data from next string 
  1461.     WorkBytes 
  1462.     % amout of data required to read from next string
  1463.     ToRead WorkBytes sub
  1464.     % Get the next string from the array of strings
  1465.     GetWorkingString
  1466.     % Get a string containing the required data, updating
  1467.     % the internal data storage
  1468.     GetWorkingBytes
  1469.     % put the data at the end of the stored data in the 
  1470.     % output string
  1471.     putinterval
  1472.   } ifelse
  1473. } bind def
  1474.  
  1475. % Given an array of glyf strings, returns an array of strings
  1476. % split on glyf boundaries
  1477. %
  1478. % [] SplitGlyf []
  1479. %
  1480. /SplitGlyf
  1481. {
  1482.   /GlyfArray exch def
  1483.   /DestArray GlyfArray length 2 mul array def
  1484.   /DestArrayIndex 0 def
  1485.  
  1486.   /LastLoca 0 def
  1487.   /NextLocaIndex 0 def
  1488.   /LastLocaIndex 0 def
  1489.     
  1490.   /GlyfStringIndex 0 def
  1491.   /WorkString maxstring string def
  1492.   /WorkBytes 0 def
  1493.   
  1494.   % Find appropriate next loca
  1495.   {
  1496.     % Get location of next glyph
  1497.     LocaArray NextLocaIndex get                      % int
  1498.     % subtract location of last point to get
  1499.     % the actual bytes between
  1500.     LastLoca sub maxstring gt                        % int bool 
  1501.     {
  1502.       LocaArray LastLocaIndex get LastLoca sub
  1503.       GetGlyfBytes                                   % ()
  1504.       DestArray DestArrayIndex 3 -1 roll put         % -
  1505.       /DestArrayIndex DestArrayIndex 1 add def       % -
  1506.       LocaArray LastLocaIndex get /LastLoca exch def % -
  1507.     } {                                              % int
  1508.       /LastLocaIndex NextLocaIndex def               % -
  1509.       /NextLocaIndex NextLocaIndex 1 add def         % -
  1510.       NextLocaIndex NumGlyphs gt                     % bool
  1511.       {
  1512.         WorkBytes                                    % int
  1513.         GlyfStringIndex GlyfArray length lt {        % int bool
  1514.           GlyfArray GlyfStringIndex get length       % int
  1515.           add string dup                             % (d) (d)
  1516.           0                                          % (d) (d) 0
  1517.           WorkString 0 WorkBytes getinterval         % (d) (d) (s)
  1518.           putinterval                                % (d)
  1519.           dup                                        % (d) (d)
  1520.           WorkBytes                                  % (d) (d) int
  1521.           GetWorkingString                           % (d) (d) int
  1522.           WorkString 0 WorkBytes getinterval         % (d) (d) int (s)
  1523.           putinterval                                % (d)
  1524.         } {
  1525.           pop                                        % -
  1526.           WorkString 0 WorkBytes getinterval         % ()
  1527.         } ifelse
  1528.         dup length string copy
  1529.         DestArray DestArrayIndex 3 -1 roll put
  1530.         exit
  1531.       } if
  1532.     } ifelse
  1533.   } loop
  1534.   DestArray
  1535.   
  1536. } bind def
  1537.  
  1538. % ProcessTTData looks at the data stored in the 'tabs' array and does several things:
  1539. % 1) Make sure strings representing tables are multiples of 4 bytes long
  1540. % 2) For arrays representing tables, make sure the total string length is a multiple
  1541. %    of 4 bytes long, to ensure the table is a multiple of 4 bytes.
  1542. % 3) Handle the glyf table specislly, each string in this array must be split on the
  1543. %    boundary of a glyf. Use the loca table to determine where the split should happen
  1544. %    and build a new array of strings split appropriately.
  1545. %
  1546. % - ProcessTTData -
  1547. %
  1548. /ProcessTTData
  1549. {
  1550.   .opdloadttfontdict begin
  1551.     % Make sure all the strings are a multiple of 4 bytes
  1552.     0 1 tabarray length 1 sub{
  1553.         /ix exch def
  1554.         tabarray ix get
  1555.         12 getu32 dup maxstring le {
  1556.           % String < 64Kb, still need to check if its a multiple of 4
  1557.           dup 4 mod 0 ne {
  1558.             4 div cvi 1 add 4 mul string /newstring exch def
  1559.             /oldstring tabs ix get def
  1560.             newstring 0 oldstring putinterval
  1561.             0 1 newstring length oldstring length sub 1 sub {
  1562.               newstring exch oldstring length add 0 put
  1563.             } for
  1564.             tabs ix newstring put
  1565.           } {
  1566.             % table size is a multiple of 4, don't need to promote it
  1567.             pop
  1568.           } ifelse
  1569.         }{
  1570.           % table size > 64K, so this is an array of strings, not a string
  1571.           % We still need to make sure that the tables end on 4-byte 
  1572.           % boundaries.
  1573.           dup 4 mod 0 ne {
  1574.             % First we need to work out how many strings of size maxstring
  1575.             % are present, and how much they contribute to the overall size.
  1576.             dup maxstring idiv maxstring mul sub
  1577.             % Promote final string length to multiple of 4
  1578.             4 idiv 1 add 4 mul string /newstring exch def
  1579.             % Get array of strings
  1580.             tabs ix get
  1581.             % find size of table and get last string
  1582.             dup length 1 sub dup /iy exch def get /oldstring exch def
  1583.             newstring 0 oldstring putinterval
  1584.             0 1 newstring length oldstring length sub 1 sub {
  1585.               newstring exch oldstring length add 0 put
  1586.             } for
  1587.             tabs ix get iy newstring put
  1588.           } {
  1589.             % table size is a multiple of 4, don't need to promote it
  1590.             pop
  1591.           } ifelse
  1592.         } ifelse
  1593.     } for
  1594.  
  1595.     % Now, if glyf table > 64Kb, then it will be an array of strings
  1596.     % We need to make sure the strings are split on glyph boundaries
  1597.     0 1 tabarray length 1 sub {            % int
  1598.       dup tabarray exch get                % int ()
  1599.       dup 12 getu32 maxstring gt {         % int () bool
  1600.         0 4 getinterval dup (glyf) eq{     % int () bool
  1601.           % Need to split the glyf strings on glyph boundaries, hmmm.
  1602.           pop                              % int
  1603.           % We need to know the number of glyphs (from the maxp table) and the
  1604.           % position of each glyph (from the loca table).
  1605.           GetLocaType                      % int
  1606.           GetNumGlyphs                     % int
  1607.           GetSortedLoca                    % int
  1608.           % Get the array of strings from tabs
  1609.           dup tabs exch get                % int
  1610.           SplitGlyf                        % int []
  1611.           tabs 3 1 roll put                % -
  1612.         } {                                % int ()
  1613.           (Warning, table ) print print ( > 64Kb\n) print
  1614.           pop                              % -
  1615.         } ifelse
  1616.       }{                                   % int ()
  1617.         % Table less than 64K, so don't worry
  1618.         pop % directory entry              % int
  1619.         pop % 'for' control variable       % -
  1620.       } ifelse
  1621.     } for
  1622.   end % .opdloadttfontdict
  1623. } bind def
  1624.     
  1625. % Makesfnts uses the accumulated data to create an array of strings
  1626. % containing only the required data.
  1627. %
  1628. % - Makesfnts array
  1629. %    
  1630. /Makesfnts
  1631. {    
  1632.   .opdloadttfontdict begin
  1633.     % Determine size of sfnts array
  1634.     % length of tabarray + header
  1635.     0
  1636.     tabs {                            % int obj
  1637.       dup type /stringtype eq {       % int obj bool
  1638.         pop                           % int
  1639.         1 add                         % int
  1640.       }{                              % int obj
  1641.         {                             % int obj
  1642.           type /stringtype eq {       % int bool
  1643.             1 add                     % int
  1644.           } if
  1645.         } forall
  1646.       } ifelse
  1647.     } forall
  1648.  
  1649.     1 add                            % add header and table directory 
  1650.                                      % to determine total # strings
  1651.     % Need to recalculate the lengths of the TT
  1652.     % tables, just in case any have changed. If required we
  1653.     % could also resort the tables here, ideally we should do so
  1654.     % and recalculate checksums, but this should never be necessary
  1655.     % for fonts produced by pdfwrite.
  1656.     /TTOffset
  1657.     TableDir length                  % initial table offset is header length
  1658.     tabarray length 16 mul add       % + (NumTables * 16) bytes
  1659.     def
  1660.     
  1661.     0
  1662.     tabarray {                     % index ()
  1663.       exch dup 1 add               % () index index+1
  1664.       3 1 roll                     % index+1 () index
  1665.       dup                          % index+1 () index index
  1666.       tabs exch get                % index+1 () index ()/[]
  1667.       dup type /stringtype eq {    % index+1 () index ()/[] bool
  1668.         length                     % index+1 () index int
  1669.         2 index exch               % index+1 () index () int
  1670.         TTOffset 
  1671.         dup 3 1 roll add           % add the running total of offsets
  1672.         /TTOffset exch def         % update running total of offsets
  1673.         8 exch putu32              % index+1 () index
  1674.         exch tabarray 3 1 roll     % index+1 [] index ()
  1675.         put                        % index+1
  1676.       } {                          % index+1 () index ()/[]
  1677.         0 exch                     % add all string lengths
  1678.         {                          % starting from 0
  1679.           dup type /stringtype eq {
  1680.             length add             %
  1681.           } {
  1682.             pop
  1683.           } ifelse
  1684.         } forall                   %
  1685.         2 index exch               % index+1 () index () int
  1686.         TTOffset 
  1687.         dup 3 1 roll add           % add the running total of offsets
  1688.         /TTOffset exch def         % update running total of offsets
  1689.         8 exch putu32              % index+1 () index
  1690.         exch tabarray 3 1 roll     % index+1 [] index ()
  1691.         put                        % index+1
  1692.       } ifelse
  1693.     } forall
  1694.     pop                            % index+1
  1695.     
  1696.     array                          % []
  1697.     dup 0                          % [] [] 0
  1698.     TableDir length            
  1699.     tables length add              % [] [] 0 header_length
  1700.     string                         % [] [] 0 ()
  1701.     dup 0 TableDir putinterval     % [] [] 0 ()
  1702.     dup 12 tables putinterval      % [] [] 0 ()
  1703.     put                            % []
  1704.     dup                            % [] []
  1705.     /ix 1 def
  1706.     tabs {                         % [] [] obj
  1707.       dup type /stringtype eq {    % [] [] obj bool
  1708.         ix exch                    % [] [] int obj
  1709.         put dup                    % [] []
  1710.         /ix ix 1 add def           % [] []
  1711.       }{
  1712.         {
  1713.           dup type /stringtype eq { % [] [] obj bool
  1714.             ix exch put dup        % [] []
  1715.             /ix ix 1 add def       %
  1716.           } {
  1717.             pop                    % [] []
  1718.           } ifelse
  1719.         } forall
  1720.       } ifelse
  1721.     } forall
  1722.     pop                            % []
  1723.     end %.opdloadttfontdict
  1724. } bind def
  1725.  
  1726. /MakeType42 % <FontFile_object> <font_descriptor> MakeType42 <FontFile_object> <font_descriptor> <font>
  1727. {
  1728.   //PDFR_DEBUG {
  1729.     (MakeType42 beg) =
  1730.   } if
  1731.   10 dict begin
  1732.     /FontName 1 index /FontName get def
  1733.     /FontType 42 def
  1734.     /FontMatrix [1 0 0 1 0 0] def
  1735.     /FontBBox 1 index /FontBBox get def          % fo fd
  1736.     dup /FontResource get                        % fo fd fr
  1737.     dup /Encoding known {                        % fo fd fr
  1738.        //PDFReader /ObtainEncoding get exec      % fo fd fr
  1739.        /Encoding get                             % fo fd e
  1740.     } {
  1741.       pop null
  1742.     } ifelse 
  1743.     /PDFEncoding exch def                        % fo fd
  1744.     /CharStrings 2 index //PDFReader /MakeTTCharStrings get exec def
  1745.     /sfnts 2 index //MakeStreamReader exec 
  1746.     ReadTTF
  1747.     ProcessTTData
  1748.     Makesfnts 
  1749.     def
  1750.     /Encoding StandardEncoding def % A stub - will be replaced by font resource.
  1751.     /PaintType 0 def
  1752.   currentdict end
  1753.   //PDFR_DEBUG {
  1754.     (MakeType42 end) =
  1755.   } if
  1756. } bind def
  1757.  
  1758. /GetInstalledFont % <name> GetInstalledFont <font>
  1759.   dup //InstalledFonts exch knownget {                          % n f
  1760.     exch pop                                                    % f
  1761.   } {                                                           % n
  1762.     dup findfont dup 3 1 roll                                   % f n f
  1763.     //InstalledFonts 3 1 roll put                               % f
  1764.   } ifelse
  1765. } bind def
  1766.  
  1767. /RemoveFontNamePrefix % <name> RemoveFontNamePrefix <name>
  1768. { //=string cvs true
  1769.   0 1 5 {
  1770.     2 index exch get //IsUpper exec not {
  1771.       pop false exit
  1772.     } if
  1773.   } for
  1774.   { (+) search {
  1775.       pop pop
  1776.     } if
  1777.   } if
  1778.   cvn
  1779. } bind def
  1780.  
  1781. /CheckFont % <key> <val> CheckFont <key> <val>
  1782. { dup /Type get /Font ne {
  1783.     mark (Resource ) 3 index ( must have /Type/Font .) //error exec
  1784.   } if
  1785. } bind def
  1786.  
  1787. /CheckEncoding %  <key> <val> CheckEncoding <key> <val>
  1788. { dup type /nametype ne {
  1789.     dup /Type get /Encoding ne {
  1790.       mark (Resource ) 3 index ( must have /Type/Encoding .) //error exec
  1791.     } if
  1792.   } if
  1793. } bind def
  1794.  
  1795. /ObtainEncoding % <font_resource> ObtainEncoding <font_resource>
  1796. { dup /Encoding known {
  1797.     dup dup /Encoding //CheckEncoding //ResolveD exec   % fr fr er|e|n
  1798.     dup type dup /arraytype eq exch /packedarraytype eq or {
  1799.       % Already resolved.
  1800.       pop pop
  1801.     } {
  1802.       dup type /nametype eq {
  1803.         /Encoding findresource                          % fr fr e
  1804.       } {
  1805.         dup /BaseEncoding //knownget exec not {
  1806.           /StandardEncoding
  1807.         } if
  1808.         /Encoding findresource                          % fr fr er e
  1809.         exch                                            % fr fr e er
  1810.         /Differences //knownget exec {                  % fr fr e d
  1811.           exch dup length array copy exch
  1812.           0 exch                                        % fr fr e 0 d
  1813.           {                                             % fr fr e i v
  1814.             dup type /integertype eq {
  1815.               exch pop
  1816.             } {
  1817.               3 copy put pop                            % fr fr e i
  1818.               1 add
  1819.             } ifelse
  1820.           } forall
  1821.           pop                                           % fr fr e
  1822.          } if                                           % fr fr e
  1823.       } ifelse                                          % fr fr e
  1824.       /Encoding exch put                                % fr
  1825.     } ifelse
  1826.   } {
  1827.     dup /Encoding /StandardEncoding /Encoding findresource put
  1828.   } ifelse
  1829. } bind def
  1830.  
  1831. /ObtainMetrics % <font_resource> ObtainMetrics <font_resource>
  1832. { dup /Widths //knownget exec {                         % fr W
  1833.     1 index /Encoding get                               % fr W E
  1834.     256 dict                                            % fr W E M
  1835.     3 index /Subtype get /TrueType eq {
  1836.       1000
  1837.     } {
  1838.       1
  1839.     } ifelse                                            % fr W E M s
  1840.     4 index /MissingWidth //knownget exec not {
  1841.       0
  1842.     } if                                                % fr W E M s mw
  1843.     5 index /FirstChar //knownget exec not {
  1844.       0
  1845.     } if                                                % fr W E M s mw c0
  1846.     6 5 roll                                            % fr E M s mw c0 W
  1847.     dup 0 exch 1 exch length 1 sub {                    % fr E M s mw c0 W i
  1848.       2 copy get                                        % fr E M s mw c0 W i w
  1849.       exch 3 index add                                  % fr E M s mw c0 W w c
  1850.       7 index exch get                                  % fr E M s mw c0 W w n
  1851.       dup null ne {
  1852.         6 index 3 1 roll exch                           % fr E M s mw c0 W M n w
  1853.         6 index div                                     
  1854.         3 copy pop //knownget exec {
  1855.           0 eq
  1856.         } {
  1857.           true
  1858.         } ifelse
  1859.         { put                                           % fr E M s mw c0 W
  1860.         } {
  1861.           pop pop pop
  1862.         } ifelse
  1863.       } {
  1864.         pop pop
  1865.       } ifelse
  1866.     } for
  1867.     pop pop pop pop exch pop                            % fr M
  1868.     1 index exch /Metrics exch put                      % fr
  1869.   } {
  1870.     dup /MissingWidth //knownget exec {                 % fr mw
  1871.       256 dict                                          % fr mw M
  1872.       2 index /Encoding get {                           % fr mw M e
  1873.         dup null ne {
  1874.           3 copy 3 2 roll put                           % fr mw M e
  1875.         } if
  1876.         pop                                             % fr mw M
  1877.       } forall
  1878.       exch pop                                          % fr M
  1879.       1 index exch /Metrics exch put                    % fr
  1880.     } if
  1881.   } ifelse
  1882. } bind def
  1883.  
  1884. /NotDef % - NotDef -
  1885. { % A Type 3 font is on dstack.
  1886.   FontMatrix aload pop pop pop exch pop exch pop        % sx sy
  1887.   1 exch div exch
  1888.   1 exch div exch                                       % wx wy
  1889.   1 index 0 setcharwidth
  1890.   o setlinewidth
  1891.   0 0 moveto
  1892.   2 copy rlineto
  1893.   1 index 0 rlineto
  1894.   neg exch neg exch rlineto                             %
  1895.   closepath stroke
  1896. } bind def
  1897.  
  1898. /BuildChar  % <font> <char_code> BuildChar -
  1899. { //PDFR_DEBUG {
  1900.     (BuildChar ) print dup //=only exec ( ) print
  1901.   } if
  1902.   exch begin
  1903.   Encoding exch get                                     % n
  1904.   //PDFR_DEBUG {
  1905.     dup =
  1906.   } if
  1907.   dup null eq {
  1908.     pop //NotDef exec                                   %
  1909.   } {                                                   % n
  1910.     CharProcs exch //knownget exec {                    % cp_stream
  1911.       //RunDelayedStream exec
  1912.     } {
  1913.       //NotDef exec
  1914.     } ifelse
  1915.   } ifelse                                              %
  1916.   end % font
  1917. } bind def
  1918.  
  1919. /printdict % <dict> printdict -
  1920. { (<<) =
  1921.   { exch = == } forall
  1922.   (>>) =
  1923. } bind def
  1924.  
  1925. /printfont % <dict> printfont -
  1926. {
  1927.   dup {
  1928.     exch dup =
  1929.     dup /Encoding eq {
  1930.       pop =
  1931.     } {
  1932.       dup /FontInfo eq exch /Private eq or {
  1933.         //printdict exec
  1934.       } {
  1935.         ==
  1936.       } ifelse
  1937.     } ifelse
  1938.   } forall
  1939. } bind def
  1940.  
  1941. /ScaleMetrics % <Metrics> <scale> ScaleMetrics <Metrics>
  1942. { 1 index {           % M s n v
  1943.     2 index div       % M s n v'
  1944.     3 index           % M s n v' M
  1945.     3 1 roll put      % M s
  1946.   } forall
  1947.   pop
  1948. } bind def
  1949.  
  1950. /ResolveAndSetFontAux  % <resource_name> <size> ResolveAndSetFont -
  1951. { exch dup                                              % s rn rn
  1952.   //PDFReader /CurrentObject get /Context get /Resources get
  1953.   /Font //DoNothing //ResolveD exec
  1954.   exch //CheckFont //ResolveD exec                      % s rn fr
  1955.   dup /Font //knownget exec {                           % s rn fr f
  1956.     exch pop exch pop
  1957.   } {
  1958.     {
  1959.       dup /Subtype get dup dup /Type1 eq exch /TrueType eq or exch /MMType1 eq or {
  1960.                                                         % s rn fr
  1961.         exch pop                                        % s fr
  1962.         dup /BaseFont get                               % s fr n
  1963.         //RemoveFontNamePrefix exec                     % s fr n
  1964.         //PDFR_DEBUG {
  1965.           (Font ) print dup =
  1966.         } if                                            % s fr n
  1967.         1 index /FontDescriptor known {                 % s fr n
  1968.           //PDFR_DEBUG {
  1969.             (Font from a font descriptor.) =
  1970.           } if
  1971.           1 index                                       % s fr n fr
  1972.           /FontDescriptor //DoNothing //ResolveD exec   % s fr n fd
  1973.           /Font //knownget exec {
  1974.             exch pop                                    % s fr fd
  1975.           } {
  1976.             //PDFR_DEBUG {
  1977.               (Font descriptor has no Font resolved.) =
  1978.             } if
  1979.             //GetInstalledFont exec                     % s fr f
  1980.           } ifelse
  1981.         } {
  1982.           //GetInstalledFont exec                       % s fr f
  1983.         } ifelse
  1984.         exch                                            % s f fr
  1985.         dup /Encoding known not {
  1986.           1 index /Encoding get 1 index exch /Encoding exch put 
  1987.         } if
  1988.         //ObtainEncoding exec
  1989.         //ObtainMetrics exec
  1990.         exch
  1991.         dup length dict copy                            % s fr f
  1992.         dup 2 index /Encoding get                       % s fr f f e
  1993.         /Encoding exch put                              % s fr f
  1994.         1 index /Metrics //knownget exec {              % s fr f M
  1995.           2 index /Subtype get /TrueType ne {
  1996.             1 index /FontMatrix get 0 get
  1997.             dup 0 eq {
  1998.           % FontMatrix[0] == 0, so cannot downscale by it
  1999.           % HACK: downscale by FontMatrix[1], and will get the target value of wx as wy
  2000.           pop
  2001.           1 index /FontMatrix get 1 get
  2002.           dup 0 eq { pop 1 } if % sorry, FontMatrix is singular so cannot enforce the PDF metrics
  2003.             } if
  2004.             0.001 div
  2005.             //ScaleMetrics exec
  2006.           }{
  2007.             % Check if we got a /sfnts key in the dict
  2008.             % If we did then we are probably OK (TT font from GS)
  2009.             1 index /sfnts known not {
  2010.               % otherwise we need to check the FontMatrix
  2011.               1 index /FontMatrix get 0 get
  2012.               dup 0 eq {
  2013.                 % FontMatrix[0] == 0, so cannot downscale by it
  2014.                 % HACK: downscale by FontMatrix[1], and will get the target value of wx as wy
  2015.                 pop
  2016.                 1 index /FontMatrix get 1 get
  2017.                 dup 0 eq { pop 1 } if % sorry, FontMatrix is singular so cannot enforce the PDF metrics
  2018.               } if
  2019.               //ScaleMetrics exec
  2020.             } if
  2021.           } ifelse
  2022.           1 index exch /Metrics exch put                % s fr f
  2023.         } if
  2024.         1 index /BaseFont get                           % s fr f n
  2025.         exch
  2026.         dup /FID undef
  2027.         dup /UniqueID undef
  2028.         definefont                                      % s fr f
  2029.         dup 3 1 roll                                    % s f fr f
  2030.         /Font exch put                                  % s f
  2031.         exit
  2032.       } if
  2033.       dup /Subtype get /Type3 eq {                      % s rn fr
  2034.         //ObtainEncoding exec
  2035.         2 copy exch /FontName exch put
  2036.         dup /CharProcs get //ResolveDict exec
  2037.         dup /FontType 3 put
  2038.         dup /BuildChar //BuildChar put
  2039.         dup dup /Font exch put
  2040.         % Ignore Metrics because pdfwrite duplicates it 
  2041.         % from setcharwidth/setcachedevice.
  2042.         dup 3 1 roll                                    % s fr rn fr
  2043.         definefont                                      % s fr f
  2044.         2 copy ne { 
  2045.           % The interpreter copied the font dictionary while 'definefont'
  2046.           % Need to update the font pointer in the resource.
  2047.           2 copy /Font exch put                         % s fr f
  2048.         } if
  2049.         exch pop                                        % s f
  2050.         exit
  2051.       } if
  2052.       dup /Subtype get /Type0 eq {                      % s rn fr
  2053.       } if
  2054.       dup /Subtype get /CIDFontType0 eq {               % s rn fr
  2055.       } if
  2056.       dup /Subtype get /CIDFontType2 eq {               % s rn fr
  2057.       } if
  2058.       mark (Unknown font type ) 2 index /Subtype get //error exec
  2059.     } loop
  2060.   } ifelse                                              % s f
  2061.   exch scalefont setfont                                %
  2062. } bind def
  2063.  
  2064. /ResolveAndSetFont  % <resource_name> <size> ResolveAndSetFont -
  2065.   //ResolveAndSetFontAux exec
  2066. } bind def
  2067.  
  2068. %%beg TrueType
  2069. % ================= Auxiliary procedures for True Type cmap Decoder =============
  2070.  
  2071. /.knownget 
  2072. { 2 copy known {
  2073.     get true
  2074.   } {
  2075.     pop pop false
  2076.   } ifelse
  2077. } bind def
  2078.  
  2079. /.min 
  2080. { 2 copy lt {
  2081.     exch
  2082.   } if
  2083.   pop
  2084. } bind def
  2085.  
  2086. /.max 
  2087. { 2 copy gt {
  2088.     exch
  2089.   } if
  2090.   pop
  2091. } bind def
  2092.  
  2093. /.dicttomark
  2094. { >>
  2095. } bind def
  2096.  
  2097. % ===================== True Type cmap Decoder =============
  2098. % The following procedures are copied from gs/lib/gs_ttf.ps with no change.
  2099.  
  2100. % <string> <index> getu16 <integer>
  2101. /getu16 {
  2102.   2 copy get 8 bitshift 3 1 roll 1 add get add
  2103. } bind def
  2104.  
  2105. % <string> <index> gets16 <integer>
  2106. /gets16 {
  2107.   getu16 16#8000 xor 16#8000 sub
  2108. } bind def
  2109.  
  2110. % <string> <index> getu32 <integer>
  2111. /getu32 {
  2112.   2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  2113. } bind def
  2114.  
  2115. % <string> <index> gets32 <integer>
  2116. /gets32 {
  2117.   2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
  2118. } bind def
  2119.  
  2120. % Each procedure in this dictionary is called as follows:
  2121. %       <encodingtable> proc <glypharray>
  2122. /cmapformats mark
  2123.   0 {           % Apple standard 1-to-1 mapping.
  2124.     6 256 getinterval { } forall 256 packedarray
  2125.   } bind
  2126.   2 {           % Apple 16bit CJK (ShiftJIS etc)
  2127.  
  2128.     % /sHK_sz           subHeaderKey_size       % 1 * uint16
  2129.     % /sH_sz            subHeader_size          % 4 * uint16
  2130.     % /sH_len           subHeader_length
  2131.     % /cmapf2_tblen     total table length
  2132.     % /cmapf2_lang      language code (not used)
  2133.     % /sHKs             subHeaderKeys
  2134.  
  2135.     /sHK_sz 2 def
  2136.     /sH_sz 8 def
  2137.     dup 2 getu16 /cmapf2_tblen exch def
  2138.  
  2139.     dup 4 getu16 /cmapf2_lang exch def
  2140.  
  2141.     dup 6 256 sHK_sz mul getinterval /sHKs exch def
  2142.  
  2143.     0           % initialization value for /sH_len
  2144.     0 1 255 {
  2145.        sHKs exch
  2146.        2 mul getu16
  2147.        1 index  % get current max
  2148.        1 index  % get current subHeaderKey
  2149.        lt {exch} if pop
  2150.     } for
  2151.     /sH_len exch def
  2152.  
  2153.     dup 6 256 sHK_sz mul add
  2154.     cmapf2_tblen 1 index sub getinterval
  2155.     /sH_gIA exch def
  2156.  
  2157.     /cmapf2_glyph_array 65535 array def
  2158.  
  2159.     /.cmapf2_putGID {
  2160.         /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
  2161.         firstCode cmapf2_ch_lo le
  2162.         cmapf2_ch_lo firstCode entryCount add lt
  2163.         and { % true: j is inside
  2164.             sH_offset idRangeOffset add         % offset to gI
  2165.             cmapf2_ch_lo firstCode sub 2 mul    % rel. pos. in range
  2166.             add 6 add                           % offset in sH_gIA
  2167.             sH_gIA exch getu16
  2168.             dup 0 gt { %
  2169.                 idDelta add
  2170.                 cmapf2_glyph_array exch cmapf2_ch exch put
  2171.             } {
  2172.                 pop
  2173.                 % cmapf2_glyph_array cmapf2_ch 0 put
  2174.             } ifelse
  2175.         } {   % false: j is outside
  2176.             % cmapf2_glyph_array cmapf2_ch 0 put
  2177.         } ifelse
  2178.     } def
  2179.  
  2180.     16#00 1 16#ff { % hi_byte scan
  2181.         /cmapf2_ch_hi exch def
  2182.         sHKs cmapf2_ch_hi sHK_sz mul getu16
  2183.         /sH_offset exch def
  2184.         sH_gIA sH_offset sH_sz getinterval
  2185.             dup 0 getu16 /firstCode exch def
  2186.             dup 2 getu16 /entryCount exch def
  2187.             dup 4 gets16 /idDelta exch def
  2188.             dup 6 getu16 /idRangeOffset exch def
  2189.         pop
  2190.         sH_offset 0 eq {
  2191.            /cmapf2_ch_lo cmapf2_ch_hi def
  2192.            /cmapf2_ch_hi 0 def
  2193.            .cmapf2_putGID
  2194.         } {
  2195.            16#00 1 16#ff { % lo_byte scan
  2196.                /cmapf2_ch_lo exch def
  2197.                .cmapf2_putGID
  2198.            } for
  2199.         } ifelse
  2200.      } for
  2201.      pop
  2202.      0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
  2203.         dup cmapf2_glyph_array exch get
  2204.         null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse
  2205.      } for
  2206.      cmapf2_glyph_array
  2207.   } bind
  2208.   4 {           % Microsoft/Adobe segmented mapping.
  2209.     /etab exch def
  2210.     /nseg2 etab 6 getu16 def
  2211.     14 /endc etab 2 index nseg2 getinterval def
  2212.                 % The Apple TrueType documentation omits the 2-byte
  2213.                 % 'reserved pad' that follows the endCount vector!
  2214.     2 add
  2215.     nseg2 add /startc etab 2 index nseg2 getinterval def
  2216.     nseg2 add /iddelta etab 2 index nseg2 getinterval def
  2217.     nseg2 add /idroff etab 2 index nseg2 getinterval def
  2218.                 % The following hack allows us to properly handle
  2219.                 % idiosyncratic fonts that start at 0xf000:
  2220.     pop
  2221.     /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
  2222.     /putglyph {
  2223.       glyphs code 3 -1 roll put /code code 1 add def
  2224.     } bind def
  2225.                 % Do a first pass to compute the size of the glyphs array.
  2226.     /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
  2227.                 % Stack: /glyphs numglyphs i2
  2228.       /i2 exch def
  2229.       /scode startc i2 getu16 def
  2230.       /ecode endc i2 getu16 def
  2231.       numcodes scode firstcode sub
  2232.                 % Hack for fonts that have only 0x0000 and 0xf000 ranges
  2233.       %dup 16#e000 ge { 255 and } if
  2234.       % the previous line is obstructive to CJK fonts, so it was removed
  2235.       exch sub 0 .max ecode scode sub 1 add add
  2236.       exch 1 index add exch
  2237.       numcodes add /numcodes exch def
  2238.     } for array def
  2239.     % prefill the array with 0's faster than a { 0 putglyph } repeat
  2240.     glyphs length 1024 ge {
  2241.       .array1024z 0 1024 glyphs length 1023 sub { glyphs exch 2 index putinterval } for
  2242.       glyphs dup length 1024 sub 3 -1 roll
  2243.       putinterval
  2244.     } {
  2245.       0 1 glyphs length 1 sub { glyphs exch 0 put } for
  2246.     } ifelse
  2247.                 % Now fill in the array.
  2248.     /numcodes 0 def /code 0 def
  2249.     0 2 nseg2 3 sub {
  2250.       /i2 exch def
  2251.       /scode startc i2 getu16 def
  2252.       /ecode endc i2 getu16 def
  2253.       numcodes scode firstcode sub
  2254.                 % Hack for fonts that have only 0x0000 and 0xf000 ranges
  2255.       %dup 16#e000 ge { 255 and } if
  2256.       % the previous line is obstructive to CJK fonts, so it was removed
  2257.       exch sub 0 .max dup /code exch code exch add def
  2258.       ecode scode sub 1 add add numcodes add /numcodes exch def
  2259.       /delta iddelta i2 gets16 def
  2260.       TTFDEBUG {
  2261.         (scode=) print scode =only
  2262.         ( ecode=) print ecode =only
  2263.         ( delta=) print delta =only
  2264.         ( droff=) print idroff i2 getu16 =
  2265.       } if
  2266.       idroff i2 getu16 dup 0 eq {
  2267.         pop scode delta add 65535 and 1 ecode delta add 65535 and
  2268.         { putglyph } for
  2269.       } {       % The +2 is for the 'reserved pad'.
  2270.         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  2271.         0 1 ecode scode sub {
  2272.           2 mul gloff add etab exch getu16
  2273.           dup 0 ne { delta add 65535 and } if putglyph
  2274.         } for
  2275.       } ifelse
  2276.     } for glyphs /glyphs null def       % for GC
  2277.   } bind
  2278.   6 {           % Single interval lookup.
  2279.     dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
  2280.     firstcode ng add array
  2281.                 % Stack: tab array
  2282.                 % Fill elements 0 .. firstcode-1 with 0
  2283.     0 1 firstcode 1 sub { 2 copy 0 put pop } for
  2284.     dup firstcode ng getinterval
  2285.                 % Stack: tab array subarray
  2286.                 % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
  2287.     0 1 ng 1 sub {
  2288.       dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
  2289.     } for pop exch pop
  2290.   } bind
  2291. .dicttomark readonly def                % cmapformats
  2292.  
  2293. % <cmaptab> cmaparray <glypharray>
  2294. /cmaparray {
  2295.   dup 0 getu16 cmapformats exch .knownget {
  2296.     TTFDEBUG {
  2297.       (cmap: format ) print 1 index 0 getu16 = flush
  2298.     } if exec
  2299.   } {
  2300.     (Can't handle format ) print 0 getu16 = flush
  2301.     0 1 255 { } for 256 packedarray
  2302.   } ifelse
  2303.   TTFDEBUG {
  2304.     (cmap: length=) print dup length = dup ==
  2305.   } if
  2306. } bind def
  2307.  
  2308. % Define remapping for misnamed glyphs in TrueType 'post' tables.
  2309. % There are probably a lot more than this!
  2310. /postremap mark
  2311.   /Cdot /Cdotaccent
  2312.   /Edot /Edotaccent
  2313.   /Eoverdot /Edotaccent
  2314.   /Gdot /Gdotaccent
  2315.   /Ldot /Ldotaccent
  2316.   /Zdot /Zdotaccent
  2317.   /cdot /cdotaccent 
  2318.   /edot /edotaccent 
  2319.   /eoverdot /edotaccent
  2320.   /gdot /gdotaccent 
  2321.   /ldot /ldotaccent
  2322.   /zdot /zdotaccent 
  2323. .dicttomark readonly def
  2324.  
  2325. /get_from_stringarray % <array|string> <offset> get_from_stringarray <int>
  2326. { 1 index type /stringtype eq {
  2327.     get
  2328.   } {
  2329.     exch {                % o ()
  2330.       2 copy length ge {
  2331.         length sub
  2332.       } {
  2333.         exch get exit
  2334.       } ifelse
  2335.     } forall
  2336.   } ifelse
  2337. } bind def
  2338.  
  2339. /getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string>
  2340. { % May allocate a string in VM.
  2341.   2 index type /stringtype eq {
  2342.     getinterval
  2343.   } {
  2344.     string exch 0                                 % [] s o p
  2345.     4 3 roll {                                    % s o p Si
  2346.       dup length                                  % s o p Si lSi
  2347.       dup 4 index lt {
  2348.         3 index exch sub                          % s o p Si o'
  2349.         exch pop 3 1 roll exch pop                % s o' p
  2350.       } {                                         % s o p Si lSi
  2351.         dup 3 1 roll                              % s o p lSi Si lSi
  2352.         4 index sub                               % s o p lSi Si lSi-o
  2353.         5 index length 4 index sub                % s o p lSi Si lSi-o ls-p
  2354.         2 copy gt { exch } if pop                 % s o p lSi Si minl
  2355.         dup 3 1 roll                              % s o p lSi minl Si minl
  2356.         5 index exch getinterval                  % s o p lSi minl from
  2357.         5 index 4 index 3 index                   % s o p lSi minl from s p minl
  2358.         getinterval                               % s o p lSi minl from to
  2359.         copy pop                                  % s o p lSi minl
  2360.         exch pop add exch pop 0 exch              % s 0 p'
  2361.         dup 3 index length ge { exit } if
  2362.       } ifelse
  2363.     } forall
  2364.     pop pop                                       % s
  2365.   } ifelse
  2366. } bind def
  2367.  
  2368. /string_array_size  % <array|string> string_array_size <int>
  2369.     { dup type /stringtype eq {
  2370.     length
  2371.   } { 
  2372.     0 exch { length add } forall
  2373.   } ifelse
  2374. } bind def
  2375.  
  2376. % Each procedure in this dictionary is called as follows:
  2377. %       posttable <<proc>> glyphencoding
  2378. /postformats mark
  2379.   16#00010000  {        % 258 standard Macintosh glyphs.
  2380.     pop MacGlyphEncoding
  2381.   }
  2382.   16#00020000  {        % Detailed map, required by Microsoft fonts.
  2383.     dup dup type /arraytype  eq { 0 get } if length 36 lt {
  2384.       TTFDEBUG { (post format 2.0 invalid.) = flush } if
  2385.       pop [ ]
  2386.     } {
  2387.       /postglyphs exch def
  2388.       /post_first postglyphs dup type /arraytype eq { 0 get } if def
  2389.       post_first 32 getu16 /numglyphs exch def
  2390.       /glyphnames numglyphs 2 mul 34 add def
  2391.       % Build names array in the order they occur in the 'post' table
  2392.       /postpos glyphnames def
  2393.       /total_length postglyphs //string_array_size exec def
  2394.       numglyphs array 0 1 numglyphs 1 sub {
  2395.     postpos total_length ge {
  2396.           % Fill the rest with .notdef
  2397.           1 numglyphs 1 sub { 1 index exch /.notdef put } for
  2398.           exit
  2399.         } if
  2400.     % No name available, /postnames will be defined as an empty
  2401.     % array and the glyph won't get a name attached.
  2402.     postglyphs postpos //get_from_stringarray exec
  2403.         postglyphs postpos 1 add 2 index //getinterval_from_stringarray exec cvn
  2404.     exch postpos add 1 add /postpos exch def
  2405.         2 index 3 1 roll
  2406.         put
  2407.       } for
  2408.       /postnames exch def
  2409.       numglyphs array 0 1 numglyphs 1 sub {
  2410.     dup 2 mul 34 add postglyphs exch 2 //getinterval_from_stringarray exec 
  2411.     dup 0 get 8 bitshift exch 1 get add dup 258 lt {
  2412.       MacGlyphEncoding exch get
  2413.     } {
  2414.       dup 32768 ge {
  2415.         % According to the published TrueType spec, such values are
  2416.         % "reserved for future use", but at least some PDF files
  2417.         % produced by the Adobe PDF library contain entries with a
  2418.         % value of 16#ffff.
  2419.         pop /.notdef
  2420.       } {
  2421.         % Get the name for this glyph
  2422.         258 sub dup postnames length ge {
  2423.           TTFDEBUG { (   *** warning: glyph index past end of 'post' table) = flush } if
  2424.           pop
  2425.           exit
  2426.         } if
  2427.         postnames exch get
  2428.         % At least some of Microsoft's TrueType fonts use incorrect
  2429.         % (Adobe-incompatible) names for some glyphs.
  2430.         % Correct for this here.
  2431.         postremap 1 index .knownget { exch pop } if
  2432.       } ifelse
  2433.     } ifelse
  2434.     2 index 3 1 roll put
  2435.       } for
  2436.  
  2437.     }
  2438.     ifelse
  2439.   } bind
  2440.   16#00030000  {        % No map.
  2441.     pop [ ]
  2442.   } bind
  2443. .dicttomark readonly def                % postformats
  2444.  
  2445. /first_post_string % - first_post_string <string>
  2446. {
  2447.   post dup type /arraytype eq { 0 get } if
  2448. } bind def
  2449.  
  2450. % - .getpost -
  2451. % Uses post, defines glyphencoding
  2452. /.getpost {
  2453.   /glyphencoding post null eq {
  2454.     TTFDEBUG { (post missing) = flush } if [ ]
  2455.   } {
  2456.     postformats first_post_string 0 getu32 .knownget {
  2457.       TTFDEBUG {
  2458.         (post: format ) print
  2459.         first_post_string
  2460.         dup 0 getu16 =only (,) print 2 getu16 = flush
  2461.       } if
  2462.       post exch exec
  2463.     } {
  2464.       TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
  2465.     } ifelse
  2466.   } ifelse def
  2467. } bind def
  2468.  
  2469. % ===================== True Type Interpretation =============
  2470.  
  2471. /TTParser <<
  2472.   /Pos 0
  2473.   /post null
  2474. >> def
  2475.  
  2476. /readu8   % <file> readu8 <int>
  2477. { read not {
  2478.     mark (Insufficient data in the stream.) //error exec
  2479.   } if
  2480. } bind def
  2481.  
  2482. /readu16   % <file> readu16 <int>
  2483. { dup //readu8 exec 8 bitshift exch //readu8 exec or
  2484. } bind def
  2485.  
  2486. /reads16   % <file> reads16 <int>
  2487. { //readu16 exec 16#8000 xor 16#8000 sub
  2488. } bind def
  2489.  
  2490. /readu32   % <file> readu32 <int>
  2491. { dup //readu16 exec 16 bitshift exch //readu16 exec or
  2492. } bind def
  2493.  
  2494. /reads32   % <file> reads32 <int>
  2495. { dup //reads16 exec 16 bitshift exch //readu16 exec or
  2496. } bind def
  2497.  
  2498. /SkipToPosition % <file> <int> SkipToPosition -
  2499. { dup //TTParser /Pos get                               % f P P p
  2500.   exch //TTParser exch /Pos exch put                    % f P p
  2501.   sub                                                   % f P-p
  2502.   //PDFR_DEBUG {
  2503.     (Skipping ) print dup //=only exec ( bytes.) =
  2504.   } if
  2505.   dup 0 eq {
  2506.     pop pop
  2507.   } {
  2508.     dup 3 1 roll                                        % P-p f P-p
  2509.     () /SubFileDecode filter                            % P-p f'
  2510.     exch                                                % f' P-p
  2511.     { 1 index //BlockBuffer readstring pop length
  2512.       dup 0 eq { pop exch pop exit } if
  2513.       sub
  2514.     } loop
  2515.     0 ne {
  2516.       mark (Insufficient data in the stream for SkipToPosition.) //error exec
  2517.     } if
  2518.   } ifelse
  2519. } bind def
  2520.  
  2521. /TagBuffer 4 string def
  2522.  
  2523. /ParseTTTableDirectory  % <file> ParseTTTableDirectory <dict>
  2524. { //PDFR_DEBUG {
  2525.     (ParseTTTableDirectory beg) =
  2526.   } if
  2527.   15 dict begin
  2528.     dup //readu32 exec 16#00010000 ne {
  2529.       mark (Unknown True Type version.) //error exec
  2530.     } if
  2531.     dup //readu16 exec /NumTables exch def
  2532.     dup //readu16 exec /SearchRange exch def
  2533.     dup //readu16 exec /EntrySelector exch def
  2534.     dup //readu16 exec /RangeShift exch def
  2535.     //PDFR_DEBUG {
  2536.       (NumTables = ) print NumTables =
  2537.     } if
  2538.     NumTables {
  2539.       dup //TagBuffer readstring not {
  2540.         mark (Could not read TT tag.) //error exec
  2541.       } if
  2542.       cvn
  2543.       [ 2 index //readu32 exec pop % CheckSum
  2544.         2 index //readu32 exec  % Offset
  2545.         3 index //readu32 exec  % Length
  2546.       ]
  2547.       //PDFR_DEBUG {
  2548.         2 copy exch //=only exec ( ) print ==
  2549.       } if
  2550.       def
  2551.     } repeat
  2552.     pop  % file
  2553.     //TTParser /Pos 12 NumTables 16 mul add put
  2554.   currentdict end
  2555.   //PDFR_DEBUG {
  2556.     (ParseTTTableDirectory end) =
  2557.   } if
  2558. } bind def
  2559.  
  2560. /ParseTTcmap  % <file> <TableDirectory> ParseTTcmap <dict>
  2561. { //PDFR_DEBUG {
  2562.     (ParseTTcmap beg) =
  2563.   } if
  2564.   /cmap get aload pop                                   % f o L
  2565.   3 1 roll                                              % L f o
  2566.   7 dict begin
  2567.     //PDFR_DEBUG {
  2568.       (Current position = ) print //TTParser /Pos get =
  2569.       (cmap position = ) print dup =
  2570.     } if
  2571.     1 index exch //SkipToPosition exec                  % L f
  2572.     //TTParser /Pos get /TablePos exch def
  2573.     dup //readu16 exec pop % version
  2574.     dup //readu16 exec /NumEncodings exch def
  2575.     //PDFR_DEBUG {
  2576.       (NumEncodings = ) print NumEncodings =
  2577.     } if
  2578.     null                                                % L f null
  2579.     NumEncodings {
  2580.       1 index //readu32 exec % platformID, specificID   % L f null id
  2581.       2 index //readu32 exec % offset                   % L f null id o
  2582.       3 array dup 3 2 roll 0 exch put                   % L f []|null id []
  2583.       2 index null ne {
  2584.         dup 0 get 3 index 0 get sub                     % L f []|null id [] l
  2585.         3 index exch 1 exch put                         % L f []|null id []
  2586.       } if
  2587.       dup 4 3 roll pop 3 1 roll                         % L f [] id []
  2588.       def
  2589.     } repeat                                            % L f []
  2590.     dup 0 get                                           % L f [] o
  2591.     4 3 roll exch sub                                   % f [] L-o
  2592.     1 exch put                                          % f
  2593.     //PDFR_DEBUG {
  2594.       currentdict {
  2595.         exch dup type /integertype eq {
  2596.           //PrintHex exec ( ) print ==
  2597.         } {
  2598.           pop pop
  2599.         } ifelse
  2600.       } forall
  2601.     } if
  2602.     4 NumEncodings 8 mul add /HeaderLength exch def
  2603.     //TTParser /Pos //TTParser /Pos get HeaderLength add put
  2604.     0                                                  % f o
  2605.     NumEncodings {
  2606.       16#7FFFFFF null                                  % f o om null|[]
  2607.       % Choosing a table with minimal offset greater than 'o' :
  2608.       currentdict {                                    
  2609.         1 index type /integertype eq {                 % f o om null|[] id []
  2610.           exch pop dup 0 get                           % f o om null|[] [] oi
  2611.           dup 5 index gt {
  2612.             dup 4 index lt {
  2613.               4 1 roll                                 % f o oi om null|[] []
  2614.               exch pop exch pop                        % f o oi []
  2615.             } {
  2616.               pop pop            
  2617.             } ifelse
  2618.           } {
  2619.             pop pop
  2620.           } ifelse                                     % f o oi []
  2621.         } {
  2622.           pop pop
  2623.         } ifelse
  2624.       } forall                                         % f o om' []
  2625.       //PDFR_DEBUG {
  2626.         (Obtaining subtable for ) print dup ==
  2627.       } if
  2628.       3 2 roll pop                                     % f o' []
  2629.       3 copy pop                                       % f o' [] f o'
  2630.       TablePos add //SkipToPosition exec               % f o' []
  2631.       3 copy exch pop 1 get                            % f o' [] l
  2632.       //TTParser /Pos //TTParser /Pos get 3 index add put
  2633.       string                                           % f o' [] f ()
  2634.       readstring not {
  2635.         mark (Can't read a cmap subtable.) //error exec
  2636.       } if                                             % f o' [] ()
  2637.       2 exch put                                       % f o'
  2638.     } repeat
  2639.     pop pop                                            %
  2640.   currentdict end                                      
  2641.   //PDFR_DEBUG {
  2642.     (ParseTTcmap end) =
  2643.   } if
  2644. } bind def
  2645.  
  2646. /GetTTEncoding   % <file> <TTcmapHeader> <platformIDspecificID> GetTTEncoding <array>
  2647. { //PDFR_DEBUG {
  2648.     (GetTTEncoding beg) =
  2649.   } if
  2650.   get                                      % f []
  2651.   exch pop                                 % []
  2652.   2 get
  2653.   10 dict begin % For local variables.
  2654.     /TTFDEBUG //PDFR_DEBUG def
  2655.     //cmaparray exec
  2656.   end
  2657.   //PDFR_DEBUG {
  2658.     (GetTTEncoding end) =
  2659.     dup ==
  2660.   } if
  2661. } bind def
  2662.  
  2663. /InverseEncoding % <encoding> InverseEncoding <dict>
  2664. {
  2665.   256 dict begin
  2666.     dup length 1 sub -1 0 {                       % E i
  2667.       2 copy get                                  % E i n
  2668.       exch                                        % E n i
  2669.       1 index currentdict exch //knownget exec {  % E n i e
  2670.         dup type /arraytype eq {
  2671.           aload length 1 add array astore         % E n e'
  2672.         } {
  2673.           2 array astore                          % E n e'
  2674.         } ifelse
  2675.       } if
  2676.       def
  2677.     } for
  2678.     pop
  2679.    currentdict end
  2680. } bind def
  2681.  
  2682. /GetMacRomanEncodingInverse
  2683. { //PDFReader /MacRomanEncodingInverse get 
  2684.   dup null eq {
  2685.     pop
  2686.     MacRomanEncoding //InverseEncoding exec
  2687.     dup //PDFReader exch /MacRomanEncodingInverse exch put
  2688.   } if
  2689. } bind def
  2690.  
  2691. /PutCharStringSingle    % <cmap_array> <glyph_name> <char_code> PutCharStringSingle  <cmap_array>
  2692. {
  2693.   dup 3 index length lt {                               % cmap name code
  2694.     2 index exch get                                    % cmap name glyphindex
  2695.     dup 0 ne {
  2696.       def                                               % cmap
  2697.     } {
  2698.       pop pop
  2699.     } ifelse
  2700.   } {
  2701.     pop pop                                             % cmap
  2702.   } ifelse
  2703. } bind def
  2704.  
  2705. /PutCharString  % <cmap_array> <glyph_name> <char_code> PutCharString  <cmap_array>
  2706. { 1 index type /nametype ne {
  2707.     mark (Bad charstring name) //error exec
  2708.   } if
  2709.   dup type /arraytype eq {
  2710.     {                                                   % cmap name code
  2711.       3 copy //PutCharStringSingle exec                 % cmap name code cmap
  2712.       pop pop                                           % cmap name
  2713.     } forall
  2714.     pop                                                 % cmap
  2715.   } {
  2716.     //PutCharStringSingle exec
  2717.   } ifelse
  2718. } bind def
  2719.  
  2720. /ComposeCharStrings % <cmaparray> <dict> ComposeCharStrings <dict>
  2721.   //PDFR_DEBUG {
  2722.     (ComposeCharStrings beg) =
  2723.   } if
  2724.   1 index length 1 add dict begin                       % cmap d
  2725.   % fixme : the dict length estimation doesn't account 'post'.
  2726.   /.notdef 0 def
  2727.   exch                                                  % d cmap
  2728.   //TTParser /post get                                  % d cmap [post]|null
  2729.   dup null ne {
  2730.     exch                                                % d [] cmap
  2731.     1 index length 1 sub -1 0 {                         % d [] cmap code
  2732.       dup 3 index exch get exch                         % d [] cmap name code
  2733.       dup 0 eq {
  2734.         pop pop
  2735.       } {
  2736.         def
  2737.       } ifelse
  2738.     } for
  2739.   } if
  2740.   exch pop exch                                         % cmap d
  2741.   {                                                     % cmap name code
  2742.     //PutCharString exec
  2743.   } forall                                              % cmap
  2744.   pop                                                   %
  2745.   currentdict end
  2746.   //PDFR_DEBUG {
  2747.     (ComposeCharStrings end) =
  2748.   } if
  2749. } bind def
  2750.  
  2751. /ParseTTpost   % <file> <TableDirectory> ParseTTpost -
  2752. { % Defines TTparser.post - an array, 
  2753.   % which maps glyph indices to glyph names.
  2754.   //PDFR_DEBUG {
  2755.     (ParseTTpost beg) =
  2756.   } if
  2757.   /post get aload pop                                   % f o L
  2758.   3 1 roll                                              % L f o
  2759.   //PDFR_DEBUG {
  2760.     (Current position = ) print //TTParser /Pos get =
  2761.     (post position = ) print dup =
  2762.   } if
  2763.   1 index exch //SkipToPosition exec                    % L f
  2764.   //TTParser /Pos //TTParser /Pos get 4 index add put
  2765.   exch dup 65535 le {
  2766.     string                                              % f s
  2767.     readstring not {
  2768.       mark (Insufficient data in the stream for ParseTTpost.) //error exec
  2769.     } if                                                % s
  2770.   } {
  2771.                                     % f s
  2772.       [ 3 1 roll                    % [ f s
  2773.       dup 16384 div floor cvi       % [ f s numblocks
  2774.       exch 1 index 16384 mul        % [ f numblocks s bytesinblocks
  2775.       sub exch                      % [ f remainder numblocks
  2776.       1 sub 0 1 3 -1 roll           % [ f remainder 0 1 numblocks
  2777.       {
  2778.         1 add index                 % [ f remainder () ()... f
  2779.         16384 string readstring not {
  2780.           mark (Insufficient data in the stream for ParseTTpost.) //error exec
  2781.         } if
  2782.       } for      
  2783.                                     % [ f remainder () ()...
  2784.       counttomark -2 roll           % [ () ()... f remainder
  2785.       string readstring not{
  2786.         mark (Insufficient data in the stream for ParseTTpost.) //error exec
  2787.       } if
  2788.       ]
  2789.   } ifelse
  2790.   1 dict begin % A bridge to the code from /gs/lib/gs_ttf.ps .
  2791.     /post exch def
  2792.     //.getpost exec
  2793.     //TTParser /post glyphencoding put
  2794.     //PDFR_DEBUG {
  2795.       (ParseTTpost end) =
  2796.       glyphencoding ==
  2797.     } if
  2798.   end
  2799. } bind def
  2800.  
  2801. /MakeTTCharStrings % <FontFile_object> MakeTTCharStrings <CharStrings>
  2802. { //MakeStreamReader exec                               % f
  2803.   dup dup //ParseTTTableDirectory exec                  % f f d
  2804.   % Since the file isn't positionable,
  2805.   % we must pick up either 'post' or 'cmap' first.
  2806.   % Deside which one we do first :
  2807.   //TTParser /post null put
  2808.   dup /post //knownget exec {
  2809.     0 get
  2810.     1 index /cmap get 0 get
  2811.     lt {
  2812.       2 copy //ParseTTpost exec                         % f f d
  2813.       //ParseTTcmap exec                                % f ch
  2814.     } {
  2815.       2 copy //ParseTTcmap exec                         % f f d ch
  2816.       3 1 roll                                          % f ch f d
  2817.       //ParseTTpost exec                                % f ch
  2818.     } ifelse
  2819.   } {
  2820.     //ParseTTcmap exec                                  % f ch
  2821.   } ifelse
  2822.   {
  2823.     dup 16#00030001 known {
  2824.       //PDFR_DEBUG {
  2825.         (Using the TT cmap encoding for Windows Unicode.) =
  2826.       } if
  2827.       16#00030001 //GetTTEncoding exec
  2828.       AdobeGlyphList //ComposeCharStrings exec
  2829.       exit
  2830.     } if
  2831.     dup 16#00010000 known {
  2832.       //PDFR_DEBUG {
  2833.         (Using the TT cmap encoding for Macintosh Roman.) =
  2834.       } if
  2835.       16#00010000 //GetTTEncoding exec 
  2836.       PDFEncoding dup null eq {
  2837.         pop //GetMacRomanEncodingInverse exec
  2838.       } {
  2839.         //InverseEncoding exec
  2840.       } ifelse
  2841.       //ComposeCharStrings exec
  2842.       exit
  2843.     } if
  2844.     dup 16#00030000 known {
  2845.       //PDFR_DEBUG {
  2846.         (Using the TT cmap encoding 3.0 - not sure why Ghostscript writes it since old versions.) =
  2847.       } if
  2848.       % Same algorithm as for 16#00010000.
  2849.       16#00030000 //GetTTEncoding exec
  2850.       PDFEncoding dup null eq {
  2851.         pop //GetMacRomanEncodingInverse exec
  2852.       } {
  2853.         //InverseEncoding exec
  2854.       } ifelse
  2855.       //ComposeCharStrings exec
  2856.       exit
  2857.     } if
  2858.     mark (True Type cmap has no useful encodings.) //error exec
  2859.   } loop
  2860.   //PDFR_DEBUG {
  2861.     (CharStrings <<) =
  2862.     dup {
  2863.       exch
  2864.       dup type /nametype eq { 
  2865.         //=only exec 
  2866.       } {
  2867.         ==
  2868.       } ifelse
  2869.       ( ) print ==
  2870.     } forall
  2871.     (>>) =
  2872.   } if
  2873. } bind def
  2874.  
  2875. %%end TrueType
  2876.  
  2877. % ===================== Functions ============================
  2878.  
  2879. /ScaleVal % <value> <Range> ScaleVal <scaled_value>
  2880. {
  2881.   aload pop                                             % v r0 r1
  2882.   1 index sub                                           % v r0 r1-r0
  2883.   3 2 roll mul add
  2884. } bind def
  2885.  
  2886. /ScaleArg % <arg> <Domain> ScaleArg <scaled_arg>
  2887. {
  2888.   aload pop                                             % a d0 d1
  2889.   1 index sub                                           % a d0 d1-d0
  2890.   3 1 roll                                              % d1-d0 a d0
  2891.   sub exch div                                          % (a-d0)/(d1-d0)
  2892. } bind def
  2893.  
  2894. /ScaleArgN % <arg1> ... <argN> <Domain> ScaleArg <scaled_arg1> ... <scaled_argN>
  2895. {
  2896.   dup length 2 sub -2 0 {                               % a1 ... an [] 2i
  2897.     2                                                   % a1 ... an [] 2i 2
  2898.     2 index 3 1 roll getinterval                        % a1 ... an [] []
  2899.     3 2 roll                                            % a1 ... [] [] an
  2900.     exch //ScaleArg exec                                % a1 ... [] an'
  2901.     1 index length 2 idiv 1 add 1 roll                  % an' a1 ... []
  2902.   } for                                                 % a1' ... an' []
  2903.   pop                                                   % a1' ... an'
  2904. } bind def
  2905.  
  2906.  
  2907. /ComputeFunction_10 % <scaled_arg> <sample_array> ComputeFunction_10 <result>
  2908. { % Assuming a 1-argument 1-result function type 0.
  2909.   //PDFR_DEBUG {
  2910.     (ComputeFunction_10 beg ) print 1 index //=only exec ( stack=) print count =
  2911.   } if
  2912.   exch                                                  % [] x
  2913.   dup 1 eq {
  2914.     pop dup length 1 sub get                            % y
  2915.   } {
  2916.     1 index length 1 sub mul                            % [] x*(l-1)
  2917.     dup dup floor sub                                   % [] x*(l-1) f
  2918.     dup 0 eq {
  2919.       pop cvi get                                       % y
  2920.     } {
  2921.       3 1 roll floor cvi                                % f [] i
  2922.       2 getinterval                                     % f []
  2923.       aload pop                                         % f y0 y1
  2924.       2 index mul 3 2 roll 1 exch sub 3 2 roll mul add  % y1*f+(1-f)*y0
  2925.     } ifelse
  2926.   } ifelse
  2927.   //PDFR_DEBUG {
  2928.     (ComputeFunction_10 end ) print dup //=only exec ( stack=) print count =
  2929.   } if
  2930. } bind def
  2931.  
  2932. /ComputeFunction_n0 % <arg1> .... <argn> <sample_array> <n> ComputeFunction_n0 <result>
  2933. { % Assuming a n-argument 1-result function type 0.
  2934.   //PDFR_DEBUG {
  2935.     (ComputeFunction_n0 beg N=) print dup //=only exec ( stack=) print count =
  2936.   } if
  2937.   dup 0 eq {                                   % v 0
  2938.     pop                                        % v
  2939.   } {                                          
  2940.     dup 2 add -1 roll                          % a2 .... an [] n a1
  2941.     dup 3 index length 1 sub ge {
  2942.       pop 1 sub                                % a2 .... an [] n-1
  2943.       exch dup length 1 sub get exch
  2944.       //PDFReader /ComputeFunction_n0 get exec
  2945.     } {
  2946.       dup floor cvi dup                        % a2 .... an [] n a1 i i
  2947.       4 index exch get                         % a2 .... an [] n a1 i [i]
  2948.       3 index dup                              % a2 .... an [] n a1 i [i] n n
  2949.       5 add copy                               % a2 .... an [] n a1 i [i] n a2 .... an [] n a1 i [i] n
  2950.       6 2 roll                                 % a2 .... an [] n a1 i [i] n a2 .... an [i] n [] n a1 i
  2951.       pop pop pop pop                          % a2 .... an [] n a1 i [i] n a2 .... an [i] n 
  2952.       1 sub                                    % a2 .... an [] n a1 i [i] n a2 .... an [i] n-1
  2953.       //PDFReader /ComputeFunction_n0 get exec % a2 .... an [] n a1 i [i] n v0
  2954.       3 2 roll pop                             % a2 .... an [] n a1 i n v0
  2955.       exch                                     % a2 .... an [] n a1 i v0 n
  2956.       4 3 roll exch                            % a2 .... an [] n i v0 a1 n
  2957.       4 add 2 roll 1 add                       % v0 a1 a2 .... an [] n i+1
  2958.       3 2 roll exch get                        % v0 a1 a2 .... an n [i+1]
  2959.       exch 1 sub                               % v0 a1 a2 .... an [i+1] n-1
  2960.       //PDFReader /ComputeFunction_n0 get exec % v0 a1 v1
  2961.       1 index mul                              % v0 a1 v1*a1
  2962.       3 1 roll                                 % v1*a1 v0 a1
  2963.       1 exch sub mul add                       % v1*a1+v0*(1-a1)
  2964.     } ifelse
  2965.   } ifelse
  2966.   //PDFR_DEBUG {
  2967.     (ComputeFunction_n0 end ) print dup //=only exec ( stack=) print count =
  2968.   } if
  2969. } bind def
  2970.  
  2971. /FunctionToProc_x01 % <function_dict> FunctionToProc_x01 <proc>
  2972. { % Assuming a n-argument 1-result function type 0.
  2973.   % The stream is already converted to the array /Data.
  2974.   dup /Domain get exch
  2975.   dup /Data get 0 get exch
  2976.   /Size get length 
  2977.   [ 4 1 roll
  2978.     //PDFR_DEBUG {
  2979.       { (function beg, stack =) print count //=only exec (\n) print } /exec load
  2980.       5 2 roll
  2981.     } if
  2982.     dup 1 gt {                                 % a1 ... an Domain Data n
  2983.       { mark exch                              % a1 ... an Domain Data [ n
  2984.         3 add 2 roll                           % Data [ a1 ... an Domain
  2985.         //ScaleArgN exec                       % Data [ a1 ... an
  2986.         counttomark dup                        % Data [ a1 ... an n n
  2987.         3 add -2 roll                          % a1 ... an n Data [
  2988.         pop exch                               % a1 ... an Data n
  2989.         //ComputeFunction_n0 exec
  2990.       } /exec load
  2991.     } {
  2992.       pop                                      % a1 Domain Data
  2993.       3 1 /roll load //ScaleArg /exec load     % Data a1s
  2994.       /exch load
  2995.       //ComputeFunction_10 /exec load
  2996.     } ifelse
  2997.     //PDFR_DEBUG {
  2998.       (function end, stack =) /print load /count load //=only /exec load (\n) /print load
  2999.     } if
  3000.   ] cvx
  3001.   //PDFR_DEBUG {
  3002.     (Made a procedure for the 1-result function :) =
  3003.     dup ==
  3004.   } if
  3005. } bind def
  3006.  
  3007. /FunctionProcDebugBeg  %  - FunctionProcDebugBeg -
  3008. { (FunctionProcDebugBeg ) print count =
  3009. } bind def
  3010.  
  3011. /FunctionProcDebugEnd  %  - FunctionProcDebugEnd -
  3012. { (FunctionProcDebugEnd ) print count =
  3013. } bind def
  3014.  
  3015. /FunctionToProc_x0n % <function_dict> <m> FunctionToProc_x0n <proc>
  3016. { % Assuming a n-argument m-result function type 0.
  3017.   % The stream is already converted to the array /Data.
  3018.   %
  3019.   % Making the procedure : { Domain //ScaleArg exec ... n copy {} exec n+1 1 roll ... }
  3020.   % except "n copy" for the last chunk.
  3021.   %
  3022.   PDFR_DEBUG {
  3023.     (FunctionToProc_x0n beg m=) print dup =
  3024.   } if
  3025.   1 index /Size get length exch                         % f n m
  3026.   dup 7 mul 2 add array                                 % f n m []
  3027.   PDFR_DEBUG {
  3028.     dup 0 //FunctionProcDebugBeg put
  3029.   } {
  3030.     dup 0 //DoNothing put
  3031.   } ifelse
  3032.   dup 1 /exec load put
  3033.   dup 2 5 index /Domain get put
  3034.   2 index 1 eq {
  3035.     dup 3 //ScaleArg put
  3036.   } {
  3037.     dup 3 //ScaleArgN put
  3038.   } ifelse
  3039.   dup 4 /exec load put
  3040.   1 index 1 sub 0 exch 1 exch {                         % f n m [] i
  3041.     dup 7 mul 5 add                                     % f n m [] i i1
  3042.     1 index 4 index 1 sub ne {
  3043.       dup 3 index exch 6 index put 1 add
  3044.       dup 3 index exch /copy load put 1 add
  3045.     } if
  3046.     [                                                   % f n m [] i i1 [
  3047.       6 index /Data get 3 index get                     % f n m [] i i1 [ di
  3048.       6 index 1 eq {
  3049.         //ComputeFunction_10 /exec load
  3050.       } {
  3051.         6 index
  3052.         //ComputeFunction_n0 /exec load
  3053.       } ifelse
  3054.     ] cvx                                               % f n m [] i i1 {}
  3055.     3 index exch 2 index exch put 1 add                 % f n m [] i i1
  3056.     2 index 1 index /exec load put 1 add
  3057.     1 index 4 index 1 sub ne {
  3058.       2 index 1 index 6 index 1 add put 1 add
  3059.       2 index 1 index 1 put 1 add
  3060.       2 index 1 index /roll load put                    % f n m [] i i1
  3061.     } if
  3062.     pop pop                                             % f n m []
  3063.   } for
  3064.   PDFR_DEBUG {
  3065.     dup dup length 2 sub //FunctionProcDebugEnd put
  3066.   } {
  3067.     dup dup length 2 sub //DoNothing put
  3068.   } ifelse
  3069.   dup dup length 1 sub /exec load put
  3070.   cvx exch pop exch pop exch pop
  3071.   //PDFR_DEBUG {
  3072.     (Made a procedure for the n-argument function :) =
  3073.     dup ==
  3074.   } if
  3075.   PDFR_DEBUG {
  3076.     (FunctionToProc_x0n end) =
  3077.   } if
  3078. } bind def
  3079.  
  3080. /MakeTableRec % <func_obj> <n> MakeTableRec <array>
  3081. {
  3082.   0 % to be bound below
  3083.   exec
  3084. } bind def
  3085.  
  3086. /MakeTable % <func_obj> <n> MakeTable <array>
  3087. { //PDFR_DEBUG {
  3088.     (MakeTable beg ) print count =
  3089.   } if
  3090.   1 index /Size get exch                                % f S N
  3091.   1 sub dup                                             % f S n n
  3092.   3 1 roll                                              % f n S n
  3093.   get                                                   % f n s
  3094.   array                                                 % f n []
  3095.   1 index 0 eq {
  3096.     exch pop exch pop                                   % []
  3097.   } {
  3098.     dup length 1 sub -1 0 {                             % f n [] i
  3099.       3 index 3 index //MakeTableRec exec               % f n [] i []
  3100.       2 index 3 1 roll put                              % f n []
  3101.     } for
  3102.     exch pop exch pop
  3103.   } ifelse
  3104.   //PDFR_DEBUG {
  3105.     (MakeTable end ) print count =
  3106.   } if
  3107. } bind def
  3108.  
  3109. //MakeTableRec 0 //MakeTable put
  3110.  
  3111. /StoreSample  % <value> <table> <dimensions> StoreSample -
  3112. { % The reader is on the dictionary stack.
  3113.   1 sub 
  3114.   dup 0 eq {
  3115.     pop                                                 % v []
  3116.   } {
  3117.     -1 1 {                                              % v T i
  3118.       I exch get get                                    % v T[I[i]]
  3119.     } for                                               % v []
  3120.   } ifelse
  3121.   I 0 get 3 2 roll put
  3122. } bind def
  3123.  
  3124. /ReadSample32   % - ReadSample32 <value>
  3125. {
  3126.   4 {
  3127.     File read not {
  3128.       mark (Insufficient data for function.) //error exec
  3129.     } if
  3130.   } repeat
  3131.   pop % Ignore the last byte because it can't fit into 'real'.
  3132.   3 1 roll exch
  3133.   256 mul add 256 mul add
  3134.   //1_24_bitshift_1_sub div
  3135. } bind def
  3136.  
  3137. /ReadSample   % - ReadSample <value>
  3138. { % The reader in on the dictionary stack.
  3139.   Buffer BitsLeft BitsPerSample
  3140.   { 2 copy ge {
  3141.       exit
  3142.     } if
  3143.     3 1 roll 
  3144.     8 add 3 1 roll
  3145.     256 mul File read not {
  3146.       mark (Insufficient data for function.) //error exec
  3147.     } if
  3148.     add
  3149.     3 1 roll
  3150.   } loop                                                % b bl pbs
  3151.   sub dup                                               % b bl-bps bl-bps
  3152.   2 index exch                                          % b bl-bps b bl-bps
  3153.   neg bitshift                                          % b bl-bps v
  3154.   2 copy exch bitshift                                  % b bl-bps v v<<(bl-bps)
  3155.   4 3 roll exch sub                                     % bl-bps v b-(v<<(bl-bps))
  3156.   /Buffer exch def                                      % bl-bps v
  3157.   exch /BitsLeft exch def                               % v
  3158.   Div div                                               % v/(1<<pbs-1)
  3159. } bind def
  3160.  
  3161. /ReadSamplesRec % <dimensions> ReadSamplesRec -
  3162. { 0 % Will be bound below
  3163.   exec
  3164. } bind def
  3165.  
  3166. /ReadSamples % <dimensions> ReadSamples -
  3167. { % The reader in on the dictionary stack.
  3168.   //PDFR_DEBUG {
  3169.     (ReadSamples beg ) print count =
  3170.   } if
  3171.   dup 1 eq {
  3172.     pop
  3173.     0 1 Size 0 get 1 sub {
  3174.       I exch 0 exch put
  3175.       0 1 M 1 sub {
  3176.         dup Range exch 2 mul 2 getinterval              % m r 
  3177.         //PDFR_DEBUG {
  3178.           (Will read a sample ... ) print
  3179.         } if
  3180.         BitsPerSample 32 eq { //ReadSample32 } { //ReadSample } ifelse
  3181.         exec exch //ScaleVal exec                       % m v
  3182.         //PDFR_DEBUG {
  3183.           (value=) print dup =
  3184.         } if
  3185.         exch Table exch get                             % v []
  3186.         Size length //StoreSample exec                  %
  3187.       } for
  3188.     } for
  3189.   } {
  3190.     1 sub 
  3191.     dup Size exch get 0 exch 1 exch 1 sub {             % d-1 i
  3192.       I exch 2 index exch put                           % d-1
  3193.       dup //ReadSamplesRec exec                         % d-1
  3194.     } for
  3195.     pop
  3196.   } ifelse
  3197.   //PDFR_DEBUG {
  3198.     (ReadSamples end ) print count =
  3199.   } if
  3200. } bind def
  3201.  
  3202. //ReadSamplesRec 0 //ReadSamples put
  3203.  
  3204. /StreamToArray % <obj> StreamToArray -
  3205. { //PDFR_DEBUG {
  3206.     (StreamToArray beg ) print count =
  3207.   } if
  3208.   userdict /FuncDataReader get begin                    % f
  3209.     dup /BitsPerSample get /BitsPerSample exch def
  3210.     dup /Size get length /N exch def
  3211.     dup /Range get length 2 idiv /M exch def
  3212.     1 BitsPerSample bitshift 1 sub /Div exch def
  3213.     /BitsLeft 0 def
  3214.     /Buffer 0 def
  3215.     dup /Size get /Size exch def                        % f
  3216.     dup /Range get /Range exch def                      % f
  3217.     /File 1 index //MakeStreamReader exec def           % f
  3218.     /I [ N { 0 } repeat ] def                           % f
  3219.     M array                                             % f []
  3220.     dup length 1 sub -1 0 {                             % f [] m
  3221.       2 index N //MakeTable exec                        % f [] m T
  3222.       2 index 3 1 roll put                              % f []
  3223.     } for
  3224.     /Table exch def                                     % f
  3225.     N //ReadSamples exec                                % f
  3226.     PDFR_DEBUG {
  3227.       (Table = ) print Table ==
  3228.     } if
  3229.     /Data Table put                                     % 
  3230.   end
  3231.   //PDFR_DEBUG {
  3232.     (StreamToArray end ) print count =
  3233.   } if
  3234. } bind def
  3235.  
  3236. /FunctionToProc10 % <function_dict> FunctionToProc10 <proc>
  3237. { % Assuming a 1-argument function type 0.
  3238.   PDFR_DEBUG {
  3239.     (FunctionToProc10 beg, Range = ) print dup /Range get ==
  3240.   } if
  3241.   dup /Order //knownget exec {
  3242.     1 ne {
  3243.       (Underimplemented function Type 0 Order 3.) =
  3244.     } if
  3245.   } if
  3246.   dup //StreamToArray exec                              % f
  3247.   dup /Range get length dup 2 eq {
  3248.     pop //FunctionToProc_x01 exec                       % proc
  3249.   } {
  3250.     2 idiv //FunctionToProc_x0n exec                    % proc
  3251.   } ifelse
  3252.   PDFR_DEBUG {
  3253.     (FunctionToProc10 end) =
  3254.   } if
  3255. } bind def
  3256.  
  3257. /FunctionToProc12 % <function_dict> FunctionToProc12 <proc>
  3258. { begin
  3259.     currentdict /C0 //knownget exec { length 1 eq } { true } ifelse {
  3260.       N
  3261.       currentdict /C0 //knownget exec {
  3262.         0 get
  3263.       } {
  3264.         0
  3265.       } ifelse
  3266.       currentdict /C1 //knownget exec {
  3267.         0 get
  3268.       } {
  3269.         1
  3270.       } ifelse
  3271.       1 index sub
  3272.       [ 4 1 roll
  3273.         {               % x n c0 c1-c0
  3274.           4 2 roll      % c0 c1-c0 x n
  3275.           excp mul add  % y
  3276.         } aload pop
  3277.       ] cvx
  3278.     } { 
  3279.         [ 
  3280.           0 1 C0 length 1 sub {
  3281.             N                                           % [ ... i n
  3282.             C0 2 index get                              % [ ... i n c0
  3283.             C1 3 index get                              % [ ... i n c0 c1
  3284.             4 3 roll pop                                % [ ... n c0 c1
  3285.             1 index sub                                 % [ ... n c0 c1-c0
  3286.             [ /dup load                                 % [ ... n c0 c1-c0 [ dup
  3287.               5 2 roll                                  % [ ... [ dup n c0 c1-c0
  3288.               {                 % x x n c0 c1-c0        
  3289.                 4 2 roll        % x c0 c1-c0 x n
  3290.                 exp mul add     % x y
  3291.                 exch            % y x
  3292.               } aload pop
  3293.             ] cvx 
  3294.             /exec load
  3295.           } for
  3296.           /pop load
  3297.         ] cvx
  3298.     } ifelse
  3299.   end
  3300.   //PDFR_DEBUG {
  3301.     (FunctionType2Proc : ) print dup == 
  3302.   } if
  3303. } bind def
  3304.  
  3305.  
  3306. /FunctionToProc14 % <function_dict> FunctionToProc14 <proc>
  3307. { //MakeStreamReader exec cvx exec
  3308.   //PDFR_DEBUG {
  3309.     (FunctionType4Proc : ) print dup == 
  3310.   } if
  3311. } bind def
  3312.  
  3313. /FunctionToProc1 % <function_dict> FunctionToProc <proc>
  3314. { % Assuming a 1-argument function.
  3315.   dup /FunctionType get
  3316.   { dup 0 eq {
  3317.       pop //FunctionToProc10 exec exit
  3318.     } if
  3319.     dup 2 eq {
  3320.       pop //FunctionToProc12 exec exit
  3321.     } if
  3322.     dup 4 eq {
  3323.       pop //FunctionToProc14 exec exit
  3324.     } if
  3325.     mark exch (Function type ) exch ( isn't implemented yet.) //error exec
  3326.   } loop
  3327. } bind def
  3328.  
  3329. /FunctionToProc20 % <function_dict> FunctionToProc20 <proc>
  3330. { % Assuming a 2-argument function type 0.
  3331.   PDFR_DEBUG {
  3332.     (FunctionToProc20, Range = ) print dup /Range get ==
  3333.   } if
  3334.   dup /Order //knownget exec {
  3335.     1 ne {
  3336.       (Underimplemented function Type 0 Order 3.) =
  3337.     } if
  3338.   } if
  3339.   dup //StreamToArray exec                              % f
  3340.   dup /Range get length dup 2 eq {
  3341.     pop //FunctionToProc_x01 exec                       % proc
  3342.   } {
  3343.     2 idiv //FunctionToProc_x0n exec                    % proc
  3344.   } ifelse
  3345. } bind def
  3346.  
  3347. /FunctionToProc % <function_dict> FunctionToProc <proc>
  3348. { //PDFR_DEBUG {
  3349.     (FunctionToProc beg ) print count =
  3350.   } if
  3351.   dup /Domain get length 2 idiv
  3352.   {
  3353.     dup 1 eq {
  3354.       pop //FunctionToProc1 exec exit
  3355.     } if
  3356.     dup 2 eq {
  3357.       pop //FunctionToProc20 exec exit
  3358.     } if
  3359.     mark (Functions with many arguments aren't implemented yet.) //error exec
  3360.   } loop
  3361.   //PDFR_DEBUG {
  3362.     (FunctionToProc end ) print count =
  3363.   } if
  3364. } bind def
  3365.  
  3366. /spotfunctions mark  % Copied from pdf_draw.ps 
  3367.   /Round {
  3368.     abs exch abs 2 copy add 1 le {
  3369.       dup mul exch dup mul add 1 exch sub 
  3370.     } {
  3371.       1 sub dup mul exch 1 sub dup mul add 1 sub
  3372.     } ifelse
  3373.   }
  3374.   /Diamond {
  3375.     abs exch abs 2 copy add .75 le {
  3376.       dup mul exch dup mul add 1 exch sub
  3377.     } {
  3378.       2 copy add 1.23 le {
  3379.         .85 mul add 1 exch sub
  3380.       } {
  3381.         1 sub dup mul exch 1 sub dup mul add 1 sub
  3382.       } ifelse
  3383.     } ifelse
  3384.   }
  3385.   /Ellipse {
  3386.     abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
  3387.       pop dup mul exch .75 div dup mul add 4 div 1 exch sub
  3388.     } {
  3389.       dup 1 gt {
  3390.         pop 1 exch sub dup mul exch 1 exch sub
  3391.         .75 div dup mul add 4 div 1 sub
  3392.       } {
  3393.         .5 exch sub exch pop exch pop
  3394.       } ifelse
  3395.     } ifelse
  3396.   }
  3397.   /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
  3398.   /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
  3399.   /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
  3400.   /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
  3401.   /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
  3402.   /Line { exch pop abs neg }
  3403.   /LineX { pop }
  3404.   /LineY { exch pop }
  3405.   /Square { abs exch abs 2 copy lt { exch } if pop neg }
  3406.   /Cross { abs exch abs 2 copy gt { exch } if pop neg }
  3407.   /Rhomboid { abs exch abs 0.9 mul add 2 div }
  3408.   /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
  3409.   /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
  3410.   /SimpleDot { dup mul exch dup mul add 1 exch sub }
  3411.   /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
  3412.   /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
  3413.   /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
  3414.   /InvertedDouble {
  3415.     exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
  3416.   }
  3417. .dicttomark readonly def
  3418.  
  3419. % ===================== Color Spaces and Colors ==============
  3420.  
  3421. /CheckColorSpace %  <key> <val> CheckColorSpace  <key> <val>
  3422. {
  3423.   dup type /arraytype ne {
  3424.     mark (Resource ) 3 index ( must be an array.) //error exec
  3425.   } if
  3426. } bind def
  3427.  
  3428. /SubstitutePDFColorSpaceRec  % <array> SubstitutePDFColorSpace <array>
  3429. { 0 % Will be bound below
  3430.   exec
  3431. } bind def
  3432.  
  3433. /SubstitutePDFColorSpace % <array> SubstitutePDFColorSpace <array>
  3434.   { 
  3435.     dup 0 get /Pattern eq {
  3436.       dup length 1 gt {
  3437.         dup dup 1 //CheckColorSpace //ResolveA exec
  3438.         dup type /nametype ne {
  3439.           //SubstitutePDFColorSpaceRec exec
  3440.         } if
  3441.         1 exch put
  3442.       } if
  3443.       exit
  3444.     } if
  3445.     dup 0 get /Indexed eq {
  3446.       exit
  3447.     } if
  3448.     dup 0 get /Separation eq {
  3449.       dup dup 2 //CheckColorSpace //ResolveA exec
  3450.       dup type /nametype ne {
  3451.         //SubstitutePDFColorSpaceRec exec
  3452.       } if
  3453.       2 exch put
  3454.       exit
  3455.     } if
  3456.     dup 0 get /CalGray eq {
  3457.       1 get                                             % dict
  3458.       dup /Gamma //knownget exec {
  3459.         [ exch /exp load ] cvx
  3460.         1 index exch /DecodeLMN exch put
  3461.       } if                              
  3462.       [ exch /CIEBasedA exch ]                          % []
  3463.       exit
  3464.     } if
  3465.     dup 0 get /CalRGB eq {
  3466.       1 get                                             % dict
  3467.       dup /Matrix //knownget exec { 
  3468.         1 index exch /MatrixLMN exch put
  3469.       } if
  3470.       dup /Gamma //knownget exec {
  3471.         aload pop
  3472.         [ exch /exp load ] cvx
  3473.         3 1 roll
  3474.         [ exch /exp load ] cvx
  3475.         3 1 roll
  3476.         [ exch /exp load ] cvx
  3477.         3 1 roll
  3478.         3 array astore
  3479.         1 index exch /DecodeLMN exch put
  3480.       } if                              
  3481.       [ exch /CIEBasedABC exch ]                        % []
  3482.       exit
  3483.     } if
  3484.     dup 0 get /Lab eq {
  3485.       1 get                                             % dict
  3486.       begin
  3487.         currentdict /Range //knownget exec { aload pop } { -100 100 -100 100 } ifelse
  3488.           0 100 6 2 roll 6 array astore 
  3489.           /RangeABC exch def
  3490.         /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
  3491.         /MatrixABC [1 1 1 1 0 0 0 0 -1] def
  3492.         { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
  3493.         /DecodeLMN [
  3494.           % Store white point implicitly inside procedures.
  3495.           [ 3 index aload pop WhitePoint 0 get /mul load ] cvx
  3496.           [ 4 index aload pop WhitePoint 1 get /mul load ] cvx
  3497.           [ 5 index aload pop WhitePoint 2 get /mul load ] cvx
  3498.         ] def pop
  3499.         //PDFR_DEBUG {
  3500.           (Constructed from Lab <<) =
  3501.           currentdict { exch = == } forall
  3502.           (>>) =
  3503.         } if
  3504.         [ /CIEBasedABC currentdict ]                    % []
  3505.       end
  3506.       exit
  3507.       pop
  3508.     } if
  3509.     mark exch (Unimplemented color space ) exch //error exec
  3510.   } loop
  3511. } bind def
  3512.  
  3513. //SubstitutePDFColorSpaceRec 0 //SubstitutePDFColorSpace put
  3514.  
  3515. /ResolveArrayElement  % <array> <index> ResolveArrayElement <array>
  3516. { 2 copy get xcheck {
  3517.     2 copy get exec
  3518.     2 index 4 1 roll put
  3519.   } {
  3520.     pop
  3521.   } ifelse
  3522. } bind def
  3523.  
  3524. /ResolveColorSpaceArrayRec  % <color_space> ResolveColorSpaceArrayRec <color_space>
  3525. { 0 % Will be bond below.
  3526.   exec
  3527. } bind def
  3528.  
  3529. /SetColorSpaceSafe % <color_space> SetColorSpaceSafe -
  3530. {
  3531.   % This works against applying a pattern over a pattern space,
  3532.   % which may happen due to duplication of stroking and non-stroking colors.
  3533.   % gs3.70 fails when setting a pattern space and 
  3534.   % the (old) current color space is a pattern space.
  3535.   %
  3536.   % If the new color space is an array and it appears equal to the old one, 
  3537.   % do nothing. Otherwise set the new color space.
  3538.   PDFR_DEBUG {
  3539.     (SetColorSpaceSafe beg) =
  3540.   } if
  3541.   currentcolorspace dup type /arraytype eq {     % cs cs'
  3542.     1 index type /arraytype eq {
  3543.       dup length 2 index length eq {
  3544.         false exch                               % cs b cs'
  3545.         dup length 0 exch 1 exch 1 sub {         % cs b cs' i
  3546.           dup                                    % cs b cs' i i
  3547.           4 index exch get exch                  % cs b cs' csi i
  3548.           2 index exch get                       % cs b cs' csi cs'i
  3549.           ne {                                   % cs b cs'
  3550.             exch pop true exch exit
  3551.           } if
  3552.         } for                                    % cs b cs'
  3553.         pop                                      % cs b
  3554.         { 
  3555.           setcolorspace
  3556.         } {
  3557.           pop
  3558.         } ifelse                                 %
  3559.       } {
  3560.         pop setcolorspace
  3561.       } ifelse
  3562.     } {
  3563.       pop setcolorspace
  3564.     } ifelse
  3565.   } {                                            % cs cs'
  3566.     pop setcolorspace
  3567.   } ifelse
  3568.   PDFR_DEBUG {
  3569.     (SetColorSpaceSafe end) =
  3570.   } if
  3571. } bind def
  3572.  
  3573. /ResolveColorSpaceArray  % <color_space> ResolveColorSpaceArray <color_space>
  3574. {
  3575.   //PDFR_DEBUG {
  3576.     (ResolveColorSpaceArray beg ) print dup ==
  3577.   } if
  3578.   dup 0 get /Indexed eq {
  3579.     1 //ResolveArrayElement exec
  3580.     dup dup 1 get 
  3581.     dup type /arraytype eq {
  3582.       //SubstitutePDFColorSpace exec 
  3583.       //ResolveColorSpaceArrayRec exec
  3584.       1 exch put
  3585.     } {
  3586.       pop pop
  3587.     } ifelse
  3588.   } if
  3589.   dup 0 get /Separation eq {
  3590.     3 //ResolveArrayElement exec
  3591.     dup 3 get //FunctionToProc exec
  3592.     2 copy 3 exch put
  3593.     pop
  3594.   } if
  3595.   PDFR_DEBUG {
  3596.     (Construcrted color space :) =
  3597.     dup ==
  3598.   } if
  3599.   //PDFR_DEBUG {
  3600.     (ResolveColorSpaceArray end ) print dup ==
  3601.   } if
  3602. } bind def
  3603.  
  3604. //ResolveColorSpaceArrayRec 0 //ResolveColorSpaceArray put
  3605.  
  3606. /ResolveColorSpace  % <name> ResolveColorSpace <color_space>
  3607.   //PDFR_DEBUG {
  3608.     (ResolveColorSpace beg ) print dup =
  3609.   } if
  3610.   dup //SimpleColorSpaceNames exch known not {
  3611.     dup //PDFColorSpaces exch //knownget exec {
  3612.       exch pop
  3613.       //PDFR_DEBUG {
  3614.         (ResolveColorSpace known ) =
  3615.       } if
  3616.     } {
  3617.       dup                                               % n n
  3618.       //PDFReader /CurrentObject get /Context get /Resources get 
  3619.       /ColorSpace //DoNothing //ResolveD exec
  3620.       exch //CheckColorSpace //ResolveD exec            % n cs
  3621.       dup type /arraytype eq {
  3622.         //SubstitutePDFColorSpace exec
  3623.         //ResolveColorSpaceArray exec
  3624.         dup //PDFColorSpaces 4 2 roll put               % []
  3625.       } if
  3626.     } ifelse
  3627.   } if
  3628.   //PDFR_DEBUG {
  3629.     (ResolveColorSpace end ) print dup ==
  3630.   } if
  3631. } bind def
  3632.  
  3633. /CheckPattern %  <key> <val> CheckPattern  <key> <val>
  3634. {
  3635.   dup /PatternType //knownget exec {
  3636.     dup 1 ne {
  3637.       mark (Resource ) 4 index ( is a shading, which can't be handled at level 2. ) //error exec
  3638.     } if
  3639.     pop
  3640.   } if
  3641.   dup /Type get /Pattern ne {
  3642.     mark (Resource ) 4 index ( must have /Type/Pattern .) //error exec
  3643.   } if
  3644. } bind def
  3645.  
  3646. /PaintProc % 
  3647. { /Context get                                          % pattern_object
  3648.   //RunDelayedStream exec
  3649. } bind def
  3650.  
  3651. /ResolvePattern % <name> ResolvePattern <pattern>
  3652. {
  3653.   dup                                                   % n n
  3654.   % Since makepattern makes a local dictionary,
  3655.   % we cahche them in userdict, which is in local VM.
  3656.   % Assuming unique resource name through the document
  3657.   userdict /PDFR_Patterns get                           % n n d
  3658.   exch //knownget exec {                                % n p
  3659.     exch pop                                            % p
  3660.   } {                                                   % n
  3661.     dup                                                 % n n
  3662.     //PDFReader /CurrentObject get /Context get /Resources get 
  3663.     /Pattern //DoNothing //ResolveD exec
  3664.     exch //CheckPattern //ResolveD exec                 % n o
  3665.     dup dup /Context exch put
  3666.     dup /Resources //DoNothing //ResolveD exec pop
  3667.     dup /PaintProc //PaintProc put
  3668.     gsave userdict /PDFR_InitialGS get setgstate
  3669.     currentglobal exch false setglobal % gs3_70 compatibility
  3670.     dup /Matrix get
  3671.     makepattern                                         % n p
  3672.     exch setglobal % gs3_70 compatibility
  3673.     grestore
  3674.     dup userdict /PDFR_Patterns get                     % n p p d
  3675.     4 2 roll                                            % p d n p
  3676.     put                                                 % p
  3677.   } ifelse
  3678. } bind def
  3679.  
  3680. /SetColor % Same arguments and result as for scn
  3681. { //PDFR_DEBUG {
  3682.     (SetColor beg) =
  3683.   } if
  3684.   currentcolorspace dup type /nametype eq {
  3685.     pop setcolor    
  3686.   } {
  3687.     0 get /Pattern eq {
  3688.       //ResolvePattern exec setpattern
  3689.     } {
  3690.       setcolor
  3691.     } ifelse
  3692.   } ifelse
  3693.   //PDFR_DEBUG {
  3694.     (SetColor end) =
  3695.   } if
  3696. } bind def
  3697.  
  3698. % ===================== Images ===============================
  3699.  
  3700. /ImageKeys 15 dict begin
  3701.   /BPC /BitsPerComponent def
  3702.   /CS /ColorSpace def
  3703.   /D /Decode def
  3704.   /DP /DecodeParms def
  3705.   /F /Filter def
  3706.   /H /Height def
  3707.   /IM /ImageMask def
  3708.   % /Intent is undefined - pdfwrite must take care of.
  3709.   /I /Interpolate def
  3710.   /W /Width def
  3711. currentdict end readonly def
  3712.  
  3713. /ImageValues 15 dict begin
  3714.   /G   /DeviceGray def
  3715.   /RGB /DeviceRGB def
  3716.   /CMYK /DeviceCMYK def 
  3717.   /I   /Indexed def
  3718.   /AHx /ASCIIHexDecode def
  3719.   /A85 /ASCII85Decode def
  3720.   /LZW /LZWDecode def
  3721.   /Fl  /FlateDecode def
  3722.   /RL  /RunLengthDecode def
  3723.   /CCF /CCITTFaxDecode def
  3724.   /DCT /DCTDecode def
  3725. currentdict end readonly def
  3726.  
  3727. /GetColorSpaceRange
  3728. { 2 index /ColorSpace get
  3729.   dup type /arraytype eq {
  3730.     1 get
  3731.   } if
  3732.   exch //knownget exec {
  3733.     exch pop
  3734.   } if
  3735. } bind def
  3736.  
  3737. /DecodeArrays 15 dict begin
  3738.   /DeviceGray { [0 1] } def
  3739.   /DeviceRGB { [0 1 0 1 0 1] } def
  3740.   /DeviceCMYK { [0 1 0 1 0 1 0 1] } def 
  3741.   /Indexed { dup /ColorSpace get 2 get [ exch 0 exch ] } def
  3742.   /Separation { [0 1] } def
  3743.   /CIEBasedA { [0 1]  /RangeA //GetColorSpaceRange exec } def
  3744.   /CIEBasedABC { [0 1 0 1 0 1] /RangeABC //GetColorSpaceRange exec } def
  3745. currentdict end readonly def
  3746.  
  3747. /Substitute % <key> <dict> Substitute <key>
  3748. { 1 index //knownget exec {
  3749.     exch pop
  3750.   } if
  3751. } bind def
  3752.  
  3753. /DebugImagePrinting  % <image_dict> DebugImagePrinting <image_dict>
  3754. {
  3755.   //PDFR_DEBUG {
  3756.     (Image :) =
  3757.     dup { exch //=only exec ( ) print == 
  3758.     } forall
  3759.   } if
  3760. } bind def
  3761.  
  3762. /CompleteImage  % <dict> CompleteImage <image_dict>
  3763. {
  3764.   dup /ColorSpace known {
  3765.     dup /ColorSpace //CheckColorSpace //ResolveD exec pop
  3766.   } if
  3767.   dup /Decode known not {
  3768.     dup /ColorSpace //knownget exec { 
  3769.       dup type /arraytype eq {
  3770.         0 get
  3771.       } if
  3772.       //DecodeArrays exch get exec 
  3773.     } {
  3774.       [0 1]
  3775.     } ifelse
  3776.     1 index exch /Decode exch put
  3777.   } if
  3778.   dup /ImageMatrix [2 index /Width get 0 0 5 index /Height get neg 
  3779.                                         0 7 index /Height get] put % Not sure why upside down ?
  3780.   //DebugImagePrinting exec
  3781. } bind def
  3782.  
  3783. /CompleteInlineImage  % <dict> CompleteInlineImage <image_dict>
  3784. {
  3785.   //PDFR_DEBUG {
  3786.     (CompleteInlineImage beg) =
  3787.   } if
  3788.   dup /ImageType known not {
  3789.     dup /ImageType 1 put
  3790.   } if
  3791.   dup length dict exch {                            % d key val
  3792.     exch //ImageKeys //Substitute exec
  3793.     dup /Filter eq {
  3794.       exch //ImageValues //Substitute exec exch
  3795.     } if
  3796.     dup /ColorSpace eq {
  3797.       exch 
  3798.       dup //ImageValues exch //knownget exec {
  3799.         exch pop
  3800.       } {
  3801.         //ResolveColorSpace exec
  3802.       } ifelse
  3803.       exch
  3804.     } if
  3805.     exch
  3806.     2 index 3 1 roll put
  3807.   } forall
  3808.   //CompleteImage exec
  3809.   dup /DataSource 2 copy get                        % d d /n f
  3810.   2 index //AppendFilters exec put
  3811.   //PDFR_DEBUG {
  3812.     (CompleteInlineImage end) =
  3813.   } if
  3814. } bind def
  3815.  
  3816. /CompleteOutlineImage  % <dict> CompleteOutlineImage <image_dict>
  3817.   currentglobal exch dup gcheck setglobal
  3818.   //PDFR_DEBUG {
  3819.     (CompleteOutlineImage beg) =
  3820.   } if
  3821.   % todo: ResetStreamReader if DataSource already exists.
  3822.   dup dup //MakeStreamReader exec /DataSource exch put
  3823.   dup /ImageType known not {
  3824.     //CompleteImage exec
  3825.     dup /ImageType 1 put
  3826.     dup /ColorSpace known {
  3827.       dup /ColorSpace //CheckColorSpace //ResolveD exec
  3828.       dup type /arraytype eq {
  3829.         //ResolveColorSpaceArray exec
  3830.         //SubstitutePDFColorSpace exec
  3831.         1 index exch /ColorSpace exch put
  3832.       } {
  3833.         pop
  3834.       } ifelse
  3835.     } if
  3836.   } if
  3837.   //PDFR_DEBUG {
  3838.     (CompleteOutlineImage end) =
  3839.   } if
  3840.   exch setglobal
  3841. } bind def
  3842.  
  3843. /DoImage % <image_dict> DoImage -
  3844. {
  3845.   //PDFR_DEBUG {
  3846.     (DoImage beg) =
  3847.   } if
  3848.   gsave
  3849.   dup /ColorSpace //knownget exec { setcolorspace } if
  3850.   dup /ImageMask //knownget exec not { false } if
  3851.   { imagemask } { image } ifelse 
  3852.   grestore
  3853.   //PDFR_DEBUG {
  3854.     (DoImage end) =
  3855.   } if
  3856. } bind def
  3857.  
  3858. % ===================== Viewer State ===============
  3859.  
  3860. /GSave % - GSave -
  3861. {
  3862.   gsave
  3863.   //PDFReader /GraphicStateStackPointer get
  3864.   dup //GraphicStateStack exch get null eq {
  3865.     dup //GraphicStateStack exch //InitialGraphicState length dict put 
  3866.   } if
  3867.   dup //GraphicStateStack exch get
  3868.   //GraphicState exch copy pop
  3869.   1 add //PDFReader exch /GraphicStateStackPointer exch put
  3870. } bind def
  3871.  
  3872. /GRestore % - GRestore -
  3873. {
  3874.   grestore
  3875.   //PDFReader /GraphicStateStackPointer get
  3876.   1 sub dup
  3877.   //PDFReader exch /GraphicStateStackPointer exch put
  3878.   //GraphicStateStack exch get
  3879.   //GraphicState copy pop
  3880. } bind def
  3881.  
  3882.  
  3883. % ===================== Interpret Data Streams ===============
  3884.  
  3885. /SetFont  % <resource_name> <size> SetFont -
  3886. { dup //GraphicState exch /FontSize exch put
  3887.   //ResolveAndSetFont exec
  3888.   //GraphicState /FontMatrixNonHV currentfont /FontMatrix get 1 get 0 ne put
  3889. } bind def
  3890.  
  3891. /ShowText  % <string> ShowText -
  3892. { //GraphicState /TextRenderingMode get 0 eq {
  3893.     //GraphicState /WordSpacing get 0
  3894.     32
  3895.     //GraphicState /CharacterSpacing get 0
  3896.     6 5 roll
  3897.     //GraphicState /FontMatrixNonHV get {
  3898.       % Use xshow to force wy in text space to be 0 (PDF1.7 5.3.3 "Text Space Details")
  3899.       %stack: wordspacing_wx wordspacing_wy space_char charspacing_wx charspacing_wy string
  3900.       [                                         % wwx wwy sp cwx cwy str [
  3901.         7 -2 roll pop                % sp cwx cwy str [ ww
  3902.         5 -2 roll pop                % sp str [ ww cw
  3903.         5 -1 roll                               % str [ ww cw sp
  3904.         {                                       % str [ ... ww cw sp c wx wy
  3905.           exch % will be removed, unless FontMatrix.xx == 0 (FontMatrixNonHV already true)
  3906.           pop                    % str [ ... ww cw sp c w
  3907.           3 index add                           % str [ ... ww cw sp c w+cw
  3908.           exch 2 index eq { 3 index add } if    % str [ ... ww cw sp w+cw[+ww]
  3909.           4 1 roll                              % str [ ... w+cw[+ww] ww cw sp
  3910.         }
  3911.         currentfont /FontMatrix get 0 get 0 ne {
  3912.           1 1 index length 1 sub getinterval cvx % drop the "exch"
  3913.         } if
  3914.         5 index                                 % str [ ww cw sp {cshowproc} str
  3915.         cshow                                   % str [ widths... ww cw sp
  3916.       pop pop pop ]                             % str [widths...]
  3917.       xshow
  3918.     } {
  3919.       awidthshow
  3920.     } ifelse
  3921.   } {
  3922.     //GraphicState /CharacterSpacing get 0 eq
  3923.     //GraphicState /FontMatrixNonHV get not and
  3924.     //GraphicState /WordSpacing get 0 eq and {
  3925.       true charpath
  3926.     } {
  3927.       % Emulate with "{ charpath } cshow".
  3928.       % Not sure how it works with CID fonts.
  3929.       {                                                 % c wx wy
  3930.         exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx == 0
  3931.         pop 0                        % (PDF1.7 5.3.3 "Text Space Details")
  3932.         currentpoint 5 4 roll                           % wx wy x y c
  3933.         ( ) dup 0 3 index put true charpath             % wx wy x y c
  3934.         5 1 roll                                        % c wx wy x y
  3935.         moveto rmoveto                                  % c
  3936.         //GraphicState /CharacterSpacing get 0 rmoveto  % c
  3937.         32 eq {                                         %
  3938.           //GraphicState /WordSpacing get 0 rmoveto
  3939.         } if
  3940.       }
  3941.       //GraphicState /FontMatrixNonHV get dup not exch {
  3942.         pop currentfont /FontMatrix get 0 get 0 ne
  3943.       } if {
  3944.         1 1 index length 1 sub getinterval cvx
  3945.       } if
  3946.       exch cshow
  3947.     } ifelse
  3948.   } ifelse
  3949. } bind def
  3950.  
  3951. /ShowTextBeg  % - ShowTextBeg -
  3952. { //GraphicState /TextRenderingMode get 0 ne {
  3953.         currentpoint newpath moveto
  3954.   } if
  3955. } bind def
  3956.  
  3957. /ShowTextEnd  % - ShowTextEnd -
  3958. { //GraphicState /TextRenderingMode get
  3959.   { dup 1 eq {
  3960.       stroke exit
  3961.     } if
  3962.     dup 2 eq {
  3963.       gsave fill grestore stroke exit
  3964.     } if
  3965.     dup 3 eq {
  3966.       currentpoint newpath moveto
  3967.     } if
  3968.     dup 4 eq {
  3969.       gsave fill grestore clip exit
  3970.     } if
  3971.     dup 5 eq {
  3972.       gsave stroke grestore clip exit
  3973.     } if
  3974.     dup 6 eq {
  3975.       gsave fill grestore gsave stroke grestore fill exit
  3976.     } if
  3977.     dup 7 eq {
  3978.       clip exit
  3979.     } if
  3980.     exit
  3981.   } loop
  3982.   pop
  3983. } bind def
  3984.  
  3985. /ShowTextWithGlyphPositioning % <array> ShowTextWithGlyphPositioning -
  3986. { //ShowTextBeg exec
  3987.   { dup type /stringtype eq {
  3988.       //ShowText exec
  3989.     } {
  3990.       neg 1000 div //GraphicState /FontSize get mul 0 rmoveto
  3991.     } ifelse
  3992.   } forall
  3993.   //ShowTextEnd exec
  3994. } bind def
  3995.  
  3996. /CheckFont % key val CheckFont key val
  3997. { dup /Type get /ExtGState ne {
  3998.     mark (Resource ) 3 index ( must have /Type/ExtGState.) //error exec
  3999.   } if
  4000. } bind def
  4001.  
  4002. /SetTransfer % <operand> SetTransfer -
  4003. {
  4004.   //PDFR_DEBUG { (SetTransfer beg ) print count = } if
  4005.   dup type /arraytype eq 1 index xcheck not and {
  4006.     0 4 getinterval aload pop 
  4007.     setcolortransfer
  4008.   } {
  4009.     settransfer
  4010.   } ifelse
  4011.   //PDFR_DEBUG { (SetTransfer end ) print count = } if
  4012. } bind def
  4013.  
  4014. /CheckExtGState % <id> <obj> CheckExtGState <id> <obj>
  4015. { dup /Type get /ExtGState ne {
  4016.     mark (Resource ) 3 index ( must have /Type/ExtGState.) //error exec
  4017.   } if
  4018. } bind def
  4019.  
  4020. /CheckHalftone % <id> <obj> CheckHalftone <id> <obj>
  4021. { dup /HalftoneType known not {
  4022.     mark (Resource ) 3 index ( must have /HalftoneType.) //error exec
  4023.   } if
  4024. } bind def
  4025.  
  4026. /ResolveFunction % <dict> <name> ResolveFunction <dict> <proc>
  4027. {
  4028.   //PDFR_DEBUG { (ResolveFunction beg ) print dup = count = } if
  4029.   2 copy get //IsObjRef exec {
  4030.     2 copy //DoNothing //ResolveD exec
  4031.     3 copy put pop
  4032.   } if
  4033.   2 copy get dup type /arraytype eq exch xcheck and not {
  4034.     2 copy get
  4035.     dup type /arraytype eq 1 index xcheck not and {
  4036.       dup length 1 sub -1 0 {
  4037.         2 copy //DoNothing ResolveA
  4038.         dup /Identity eq {
  4039.           pop 2 copy {} put
  4040.         } {
  4041.           //FunctionToProc exec
  4042.           3 copy put pop
  4043.         } ifelse
  4044.         pop
  4045.       } for
  4046.     } {
  4047.       dup /Default eq {
  4048.         % Leave it. ExtGState methods will resolve.
  4049.       } {
  4050.         dup /Identity eq {
  4051.           pop {}
  4052.         } { dup type /nametype eq {
  4053.             //spotfunctions exch get
  4054.           } {
  4055.             //FunctionToProc exec
  4056.           } ifelse
  4057.         } ifelse
  4058.       } ifelse
  4059.     } ifelse
  4060.     3 copy put
  4061.     exch pop
  4062.   } {
  4063.     1 index exch get
  4064.   } ifelse
  4065.   //PDFR_DEBUG { (ResolveFunction end ) print dup == count = } if
  4066. } bind def
  4067.  
  4068. /ResolveFunctionSafe % <dict> <name> ResolveFunctionSafe <dict>
  4069. { 2 copy known {
  4070.   //ResolveFunction exec
  4071.   } if
  4072.   pop
  4073. } bind def
  4074.  
  4075. /CreateHalftoneThresholds  % <halftone_dict> CreateHalftoneThresholds <halftone_dict>
  4076. {
  4077.   dup /Thresholds known not {
  4078.     dup /HalftoneType get 10 eq {
  4079.       dup dup //MakeStreamReader exec
  4080.       /Thresholds exch put
  4081.     } if
  4082.     dup /HalftoneType get dup 3 eq exch 6 eq or {
  4083.       dup dup //MakeStreamReader exec
  4084.       //BlockBuffer readstring pop
  4085.       dup length 
  4086.       dup 0 eq {
  4087.         mark (Could not read Thresholds) //error exec
  4088.       } if
  4089.       string copy /Thresholds exch put
  4090.       dup /HalftoneType 3 put % replace Type 6 with Type 3.
  4091.     } if
  4092.   } if
  4093. } bind def
  4094.  
  4095.  
  4096. /SetExtGState % <name> SetExtGState -
  4097. {
  4098.   //PDFReader /CurrentObject get /Context get /Resources get 
  4099.   /ExtGState //DoNothing //ResolveD exec
  4100.   exch //CheckExtGState //ResolveD exec         % s gs
  4101.   dup /LW //knownget exec {
  4102.     setlinewidth
  4103.   } if
  4104.   dup /LC //knownget exec {
  4105.     setlinecap
  4106.   } if
  4107.   dup /LJ //knownget exec {
  4108.     setlinejoin
  4109.   } if
  4110.   dup /ML //knownget exec {
  4111.     setmeterlimit
  4112.   } if
  4113.   dup /D //knownget exec {
  4114.     setdash
  4115.   } if
  4116.   dup /RI //knownget exec {
  4117.     % Ghostscript never writes it.
  4118.     mark (Unimplemented ExtGState.RI) //error exec
  4119.   } if
  4120.   dup /OP //knownget exec {
  4121.     % pdfwrite must take care of stroking/filling
  4122.     setoverprint
  4123.   } if
  4124.   dup /op //knownget exec {
  4125.     setoverprint
  4126.   } if
  4127.   dup /OPM //knownget exec {
  4128.     % pdfwrite must take care of.
  4129.     mark (Unimplemented ExtGState.OPM) //error exec
  4130.   } if
  4131.   dup /Font //knownget exec {
  4132.     % Ghostscript never writes it.
  4133.     mark (Unimplemented ExtGState.Font) //error exec
  4134.   } if
  4135.   dup /BG known {
  4136.     /BG //ResolveFunction exec
  4137.     setblackgeneration
  4138.   } if
  4139.   dup /BG2 known {
  4140.     /BG2 //ResolveFunction exec
  4141.     dup /Default eq {
  4142.       //InitialExtGState /BG2 get
  4143.     } if
  4144.     setblackgeneration
  4145.   } if
  4146.   dup /UCR known {
  4147.     /UCR //ResolveFunction exec
  4148.     setundercolorremoval
  4149.   } if
  4150.   dup /UCR2 known {
  4151.     /UCR2 //ResolveFunction exec
  4152.     dup /Default eq {
  4153.       //InitialExtGState /UCR2 get
  4154.     } if
  4155.     setundercolorremoval
  4156.   } if
  4157.   dup /TR known {
  4158.     /TR //ResolveFunction exec
  4159.     //SetTransfer exec
  4160.   } if
  4161.   dup /TR2 known {
  4162.     /TR2 //ResolveFunction exec
  4163.     dup /Default eq {
  4164.       pop //InitialExtGState /TR2 get
  4165.       aload pop setcolortransfer
  4166.     } {
  4167.       //SetTransfer exec
  4168.     } ifelse
  4169.   } if
  4170.   dup /HT //knownget exec {
  4171.     dup /Default eq {
  4172.       pop //InitialExtGState /HT get
  4173.       sethalftone
  4174.     } {
  4175.       //PDFR_DEBUG { (Ht beg) = } if
  4176.       pop dup /HT //CheckHalftone //ResolveD exec
  4177.       /SpotFunction //ResolveFunctionSafe exec
  4178.       /TransferFunction //ResolveFunctionSafe exec
  4179.       null exch
  4180.       dup /HalftoneType get dup 5 eq exch dup 4 eq exch 2 eq or or {
  4181.         dup {                             % null h n v
  4182.           dup //IsObjRef exec {
  4183.             pop
  4184.             1 index exch //CheckHalftone ResolveD
  4185.           } if
  4186.           dup type /dicttype eq {
  4187.             dup /SpotFunction //ResolveFunctionSafe exec
  4188.             /TransferFunction //ResolveFunctionSafe exec
  4189.             //CreateHalftoneThresholds exec
  4190.             dup /HalftoneType get 5 gt {    % null h n v
  4191.               4 3 roll pop 
  4192.               dup 4 1 roll
  4193.             } if
  4194.           } if
  4195.           pop pop
  4196.         } forall
  4197.       } if
  4198.       //CreateHalftoneThresholds exec
  4199.       //PDFR_DEBUG {
  4200.         (HT:)= 
  4201.         dup { 
  4202.           1 index /Default eq {
  4203.             (Default <<)=
  4204.               exch pop
  4205.               { exch = == } forall
  4206.             (>>)=
  4207.           } {
  4208.             exch = ==
  4209.           } ifelse
  4210.         } forall 
  4211.         (HT end)= flush
  4212.       } if
  4213.       exch dup null ne {
  4214.         (Warning: Ignoring a halftone with a Level 3 component halftone Type ) print dup /HalftoneType get =
  4215.         pop pop
  4216.       } {
  4217.         pop
  4218.         dup /HalftoneType get 5 gt {
  4219.           (Warning: Ignoring a Level 3 halftone Type ) print dup /HalftoneType get =
  4220.           pop
  4221.         } {
  4222.           sethalftone
  4223.         } ifelse
  4224.       } ifelse
  4225.       //PDFR_DEBUG { (HT set)= flush } if
  4226.     } ifelse
  4227.   } if
  4228.   dup /FL //knownget exec {
  4229.     setflattness
  4230.   } if
  4231.   dup /SM //knownget exec {
  4232.     setsmoothness
  4233.   } if
  4234.   dup /SA //knownget exec {
  4235.     setstrokeadjust
  4236.   } if
  4237.   dup /BM //knownget exec {
  4238.     % pdfwrite must take care of.
  4239.     mark (Unimplemented ExtGState.BM) //error exec
  4240.   } if
  4241.   dup /SMask //knownget exec {
  4242.     % pdfwrite must take care of.
  4243.     mark (Unimplemented ExtGState.SMask) //error exec
  4244.   } if
  4245.   dup /CA //knownget exec {
  4246.     % pdfwrite must take care of.
  4247.     mark (Unimplemented ExtGState.CA) //error exec
  4248.   } if
  4249.   dup /ca //knownget exec {
  4250.     % pdfwrite must take care of.
  4251.     mark (Unimplemented ExtGState.ca) //error exec
  4252.   } if
  4253.   dup /AIS //knownget exec {
  4254.     % pdfwrite must take care of.
  4255.     mark (Unimplemented ExtGState.AIS) //error exec
  4256.   } if
  4257.   dup /TK //knownget exec {
  4258.     % pdfwrite must take care of.
  4259.     mark (Unimplemented ExtGState.TK) //error exec
  4260.   } if
  4261.   pop
  4262. } bind def
  4263.  
  4264. /CheckXObject  % <id> <obj> CheckHalftone <id> <obj>
  4265. { dup /Subtype get dup /Image ne exch dup /Form ne exch /PS ne and and {
  4266.     mark (Resource ) 3 index ( must have /Subtype /Image or /Form or /PS.) //error exec
  4267.   } if
  4268. } bind def
  4269.  
  4270. /DoXObject % <name> DoXObject -
  4271. {
  4272.   //PDFReader /CurrentObject get /Context get /Resources get 
  4273.   /XObject //DoNothing //ResolveD exec
  4274.   exch //CheckXObject //ResolveD exec
  4275.   dup /Subtype get
  4276.   dup /Image eq {
  4277.     pop
  4278.     //CompleteOutlineImage exec
  4279.     //DoImage exec
  4280.   } {
  4281.     dup /PS eq {
  4282.       PDFR_DEBUG {
  4283.         (Executing a PS Xobject) =
  4284.       } if
  4285.       pop
  4286.       //RunDelayedStream exec
  4287.     } {
  4288.       dup /Form eq {
  4289.         pop
  4290.         PDFR_DEBUG {
  4291.           (Executing a Form XObject) =
  4292.         } if
  4293.         //PDFReader /CurrentObject get exch
  4294.         dup //PDFReader exch << exch /Context exch >> /CurrentObject exch put
  4295.         dup /Matrix get concat
  4296.         dup /BBox get aload pop exch 3 index sub exch 2 index sub rectclip
  4297.         //RunDelayedStream exec
  4298.         //PDFReader exch /CurrentObject exch put
  4299.       } {
  4300.         mark exch (unimplemented XObject type ) exch //error exec
  4301.       } ifelse
  4302.     } ifelse
  4303.   } ifelse
  4304. } bind def
  4305.  
  4306. /Operators 50 dict begin
  4307.   /q { //GSave exec } bind def
  4308.   /Q { //GRestore exec } bind def
  4309.   /cm { //TempMatrix astore concat } bind def
  4310.   /i { 1 .min setflat } bind def
  4311.   /J /setlinecap load def
  4312.   /d /setdash load def
  4313.   /j /setlinejoin load def
  4314.   /w /setlinewidth load def
  4315.   /M /setmiterlimit load def
  4316.   /gs { SetExtGState } bind def
  4317.  
  4318.   /g /setgray load def
  4319.   /rg /setrgbcolor load def
  4320.   /k /setcmykcolor load def
  4321.   /cs { //ResolveColorSpace exec //SetColorSpaceSafe exec
  4322.       } bind def
  4323.   /sc /setcolor load def
  4324.   /scn { //SetColor exec } bind def
  4325.   /G /setgray load def
  4326.   /RG /setrgbcolor load def
  4327.   /K /setcmykcolor load def
  4328.   /CS //cs def
  4329.   /ri { SetColorRenderingIntent } bind def
  4330.   /SC /setcolor load def
  4331.   /SCN { //SetColor exec } bind def
  4332.  
  4333.   /m /moveto load def
  4334.   /l /lineto load def
  4335.   /c /curveto load def
  4336.   /v { currentpoint 6 2 roll curveto } bind def
  4337.   /y { 2 copy curveto } bind def
  4338.   /re {
  4339.     4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
  4340.     closepath
  4341.   } def
  4342.   /h /closepath load def
  4343.   /n /newpath load def
  4344.   /S /stroke load def
  4345.   /s { closepath stroke } bind def
  4346.   /f /fill load def
  4347.   /f* /eofill load def
  4348.   /B { gsave fill grestore stroke } bind def
  4349.   /b { closepath gsave fill grestore stroke } bind def
  4350.   /B* { gsave eofill grestore stroke } bind def
  4351.   /b* { closepath gsave eofill grestore stroke } bind def
  4352.   /W /clip load def
  4353.   /W* /eoclip load def
  4354.   /sh { % Reserved for ps3write.
  4355.         ResolveShading 
  4356.         dup /Background known {
  4357.           gsave
  4358.           dup /ColorSpace get setcolorspace
  4359.           dup /Background get aload pop setcolor
  4360.           pathbbox               % x0 y0 x1 y1
  4361.           2 index sub exch 3 index sub exch
  4362.           rectfill
  4363.           grestore
  4364.         } if
  4365.         shfill 
  4366.       } bind def
  4367.  
  4368.   /Do { //DoXObject exec } bind def
  4369.  
  4370.   /BI { currentglobal false setglobal << } bind def
  4371.   /ID { >>
  4372.         dup /DataSource currentfile 
  4373.         % HACK BEG
  4374.         % This hack provides a compatibility to HP LaserJet 1320,
  4375.         % which sometimes closes the underlying stream when EOD 
  4376.         % is reached in the ASCII85Decode filter.
  4377.         % This portion is not required by the Postscript language definition.
  4378.         2 index /F //knownget exec {
  4379.           /A85 eq {
  4380.             0 (~>) /SubFileDecode filter 
  4381.           } if
  4382.         } if
  4383.         % HACK END
  4384.         put
  4385.         //CompleteInlineImage exec
  4386.         exch setglobal
  4387.         //DoImage exec
  4388.       } bind def
  4389.   /EI {} bind def
  4390.  
  4391.   /BT { gsave //GraphicState /InitialTextMatrix get currentmatrix pop } bind def
  4392.   /ET { grestore } bind def
  4393.   /Tc { //GraphicState exch /CharacterSpacing exch put } bind def
  4394.   /TL { //GraphicState exch /TextLeading exch put } bind def
  4395.   /Tr { //GraphicState exch /TextRenderingMode exch put } bind def
  4396.   /Ts {  % Ghostscript never generates it.
  4397.         mark (Unimplemented SetTextRise) //error exec
  4398.       } bind def
  4399.   /Tw { //GraphicState exch /WordSpacing exch put } bind def
  4400.   /Tz { % Ghostscript never generates it.
  4401.             mark (Unimplemented SetHorizontalTextScaling) //error exec
  4402.       } bind def
  4403.   /Td { translate 0 0 moveto } bind def
  4404.   /TD { dup neg //TL exec //Td exec } bind def
  4405.   /Tm { //GraphicState /InitialTextMatrix get setmatrix
  4406.         //TempMatrix astore concat
  4407.         0 0 moveto } bind def
  4408.   /T* { 0 //GraphicState /TextLeading get neg //Td exec } bind def
  4409.   /Tj { //ShowTextBeg exec  //ShowText exec  //ShowTextEnd exec } bind def
  4410.   /'  { //T* exec  //ShowText exec  //ShowTextEnd exec } bind def
  4411.   /"  { 3 2 roll //Tw exec exch //Tc exec //' exec} bind def
  4412.   /TJ //ShowTextWithGlyphPositioning def
  4413.   /Tf //SetFont def
  4414.  
  4415.   /d0 /setcharwidth load def
  4416.   /d1 /setcachedevice load def
  4417.  
  4418.   /BDC { BeginMarkedContentSequenceWithPropertyList } bind def
  4419.   /BMC { BeginMarkedContentSequence } bind def
  4420.   /EMC { EndMarkedContentSequence } bind def
  4421.   /BX { BeginCompatibilitySection } bind def
  4422.   /EX { EndCompatibilitySection } bind def
  4423.   /DP { DefineMarkedContentPointWithPropertyList } bind def
  4424.   /MP { DefineMarkedContentPoint } bind def
  4425.   /PS { cvx exec } bind def
  4426. currentdict end def
  4427.  
  4428. //PDFR_STREAM {
  4429.   % Rebind operators with a debug tracing.
  4430.   //Operators length dict begin
  4431.   //Operators {                                 % n p
  4432.     exch dup                                    % p n n
  4433.     [ exch //=only /exec load                   % p n [ n =only exec
  4434.       ( ) /print load                           % p n [ n =only exec () print
  4435.       8 7 roll                                  % n [ n =only exec () print p
  4436.       dup type /arraytype eq {
  4437.         /exec load                              % n [ n =only exec () print p exec
  4438.       } if
  4439.       ( ) /print load
  4440.     ] cvx                                       % n {}
  4441.     def
  4442.   } forall
  4443.   currentdict end /Operators exch def
  4444. } if
  4445.  
  4446. % Functions for handling Ghostscript library files that define encodings.
  4447.  
  4448. /.registerencoding
  4449. { pop pop
  4450. } bind def
  4451.  
  4452. /.defineencoding
  4453. { def
  4454. } bind def
  4455.  
  4456. /.findencoding
  4457. { load
  4458. } bind def
  4459.  
  4460.  
  4461. % Leaving the procset on the dictionary stack to provide 
  4462. % definitions of obj, endobj, stream, endstream, R, xref.
  4463. %%EndPrologue
  4464.